1 // SPDX-License-Identifier: GPL-2.0-only
2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
3 #include <linux/module.h>
4 #include <linux/kernel.h>
6 #include <linux/capability.h>
8 #include <linux/inetdevice.h>
10 #include <linux/list.h>
11 #include <linux/rculist.h>
12 #include <linux/skbuff.h>
13 #include <linux/slab.h>
14 #include <linux/tcp.h>
19 #include <linux/netfilter/nfnetlink.h>
20 #include <linux/netfilter/x_tables.h>
21 #include <net/netfilter/nf_log.h>
22 #include <linux/netfilter/nfnetlink_osf.h>
25 * Indexed by dont-fragment bit.
26 * It is the only constant value in the fingerprint.
28 struct list_head nf_osf_fingers
[2];
29 EXPORT_SYMBOL_GPL(nf_osf_fingers
);
31 static inline int nf_osf_ttl(const struct sk_buff
*skb
,
32 int ttl_check
, unsigned char f_ttl
)
34 struct in_device
*in_dev
= __in_dev_get_rcu(skb
->dev
);
35 const struct iphdr
*ip
= ip_hdr(skb
);
36 const struct in_ifaddr
*ifa
;
39 if (ttl_check
== NF_OSF_TTL_TRUE
)
40 return ip
->ttl
== f_ttl
;
41 if (ttl_check
== NF_OSF_TTL_NOCHECK
)
43 else if (ip
->ttl
<= f_ttl
)
46 in_dev_for_each_ifa_rcu(ifa
, in_dev
) {
47 if (inet_ifa_match(ip
->saddr
, ifa
)) {
48 ret
= (ip
->ttl
== f_ttl
);
56 struct nf_osf_hdr_ctx
{
60 const unsigned char *optp
;
64 static bool nf_osf_match_one(const struct sk_buff
*skb
,
65 const struct nf_osf_user_finger
*f
,
67 struct nf_osf_hdr_ctx
*ctx
)
69 const __u8
*optpinit
= ctx
->optp
;
70 unsigned int check_WSS
= 0;
71 int fmatch
= FMATCH_WRONG
;
75 if (ctx
->totlen
!= f
->ss
|| !nf_osf_ttl(skb
, ttl_check
, f
->ttl
))
79 * Should not happen if userspace parser was written correctly.
81 if (f
->wss
.wc
>= OSF_WSS_MAX
)
87 for (optnum
= 0; optnum
< f
->opt_num
; ++optnum
)
88 foptsize
+= f
->opt
[optnum
].length
;
90 if (foptsize
> MAX_IPOPTLEN
||
91 ctx
->optsize
> MAX_IPOPTLEN
||
92 ctx
->optsize
!= foptsize
)
95 check_WSS
= f
->wss
.wc
;
97 for (optnum
= 0; optnum
< f
->opt_num
; ++optnum
) {
98 if (f
->opt
[optnum
].kind
== *ctx
->optp
) {
99 __u32 len
= f
->opt
[optnum
].length
;
100 const __u8
*optend
= ctx
->optp
+ len
;
104 switch (*ctx
->optp
) {
110 mss
= ntohs((__force __be16
)mss
);
118 fmatch
= FMATCH_OPT_WRONG
;
120 if (fmatch
!= FMATCH_OK
)
124 if (fmatch
!= FMATCH_OPT_WRONG
) {
125 fmatch
= FMATCH_WRONG
;
129 if (f
->wss
.val
== 0 || ctx
->window
== f
->wss
.val
)
134 * Some smart modems decrease mangle MSS to
135 * SMART_MSS_2, so we check standard, decreased
136 * and the one provided in the fingerprint MSS
139 #define SMART_MSS_1 1460
140 #define SMART_MSS_2 1448
141 if (ctx
->window
== f
->wss
.val
* mss
||
142 ctx
->window
== f
->wss
.val
* SMART_MSS_1
||
143 ctx
->window
== f
->wss
.val
* SMART_MSS_2
)
147 if (ctx
->window
== f
->wss
.val
* (mss
+ 40) ||
148 ctx
->window
== f
->wss
.val
* (SMART_MSS_1
+ 40) ||
149 ctx
->window
== f
->wss
.val
* (SMART_MSS_2
+ 40))
153 if ((ctx
->window
% f
->wss
.val
) == 0)
159 if (fmatch
!= FMATCH_OK
)
160 ctx
->optp
= optpinit
;
162 return fmatch
== FMATCH_OK
;
165 static const struct tcphdr
*nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx
*ctx
,
166 const struct sk_buff
*skb
,
167 const struct iphdr
*ip
,
169 struct tcphdr
*_tcph
)
171 const struct tcphdr
*tcp
;
173 tcp
= skb_header_pointer(skb
, ip_hdrlen(skb
), sizeof(struct tcphdr
), _tcph
);
180 ctx
->totlen
= ntohs(ip
->tot_len
);
181 ctx
->df
= ntohs(ip
->frag_off
) & IP_DF
;
182 ctx
->window
= ntohs(tcp
->window
);
184 if (tcp
->doff
* 4 > sizeof(struct tcphdr
)) {
185 ctx
->optsize
= tcp
->doff
* 4 - sizeof(struct tcphdr
);
187 ctx
->optp
= skb_header_pointer(skb
, ip_hdrlen(skb
) +
188 sizeof(struct tcphdr
), ctx
->optsize
, opts
);
195 nf_osf_match(const struct sk_buff
*skb
, u_int8_t family
,
196 int hooknum
, struct net_device
*in
, struct net_device
*out
,
197 const struct nf_osf_info
*info
, struct net
*net
,
198 const struct list_head
*nf_osf_fingers
)
200 const struct iphdr
*ip
= ip_hdr(skb
);
201 const struct nf_osf_user_finger
*f
;
202 unsigned char opts
[MAX_IPOPTLEN
];
203 const struct nf_osf_finger
*kf
;
204 int fcount
= 0, ttl_check
;
205 int fmatch
= FMATCH_WRONG
;
206 struct nf_osf_hdr_ctx ctx
;
207 const struct tcphdr
*tcp
;
210 memset(&ctx
, 0, sizeof(ctx
));
212 tcp
= nf_osf_hdr_ctx_init(&ctx
, skb
, ip
, opts
, &_tcph
);
216 ttl_check
= (info
->flags
& NF_OSF_TTL
) ? info
->ttl
: 0;
218 list_for_each_entry_rcu(kf
, &nf_osf_fingers
[ctx
.df
], finger_entry
) {
222 if (!(info
->flags
& NF_OSF_LOG
) && strcmp(info
->genre
, f
->genre
))
225 if (!nf_osf_match_one(skb
, f
, ttl_check
, &ctx
))
232 if (info
->flags
& NF_OSF_LOG
)
233 nf_log_packet(net
, family
, hooknum
, skb
,
235 "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
236 f
->genre
, f
->version
, f
->subtype
,
237 &ip
->saddr
, ntohs(tcp
->source
),
238 &ip
->daddr
, ntohs(tcp
->dest
),
241 if ((info
->flags
& NF_OSF_LOG
) &&
242 info
->loglevel
== NF_OSF_LOGLEVEL_FIRST
)
246 if (!fcount
&& (info
->flags
& NF_OSF_LOG
))
247 nf_log_packet(net
, family
, hooknum
, skb
, in
, out
, NULL
,
248 "Remote OS is not known: %pI4:%u -> %pI4:%u\n",
249 &ip
->saddr
, ntohs(tcp
->source
),
250 &ip
->daddr
, ntohs(tcp
->dest
));
255 return fmatch
== FMATCH_OK
;
257 EXPORT_SYMBOL_GPL(nf_osf_match
);
259 bool nf_osf_find(const struct sk_buff
*skb
,
260 const struct list_head
*nf_osf_fingers
,
261 const int ttl_check
, struct nf_osf_data
*data
)
263 const struct iphdr
*ip
= ip_hdr(skb
);
264 const struct nf_osf_user_finger
*f
;
265 unsigned char opts
[MAX_IPOPTLEN
];
266 const struct nf_osf_finger
*kf
;
267 struct nf_osf_hdr_ctx ctx
;
268 const struct tcphdr
*tcp
;
271 memset(&ctx
, 0, sizeof(ctx
));
273 tcp
= nf_osf_hdr_ctx_init(&ctx
, skb
, ip
, opts
, &_tcph
);
277 list_for_each_entry_rcu(kf
, &nf_osf_fingers
[ctx
.df
], finger_entry
) {
279 if (!nf_osf_match_one(skb
, f
, ttl_check
, &ctx
))
282 data
->genre
= f
->genre
;
283 data
->version
= f
->version
;
289 EXPORT_SYMBOL_GPL(nf_osf_find
);
291 static const struct nla_policy nfnl_osf_policy
[OSF_ATTR_MAX
+ 1] = {
292 [OSF_ATTR_FINGER
] = { .len
= sizeof(struct nf_osf_user_finger
) },
295 static int nfnl_osf_add_callback(struct net
*net
, struct sock
*ctnl
,
296 struct sk_buff
*skb
, const struct nlmsghdr
*nlh
,
297 const struct nlattr
* const osf_attrs
[],
298 struct netlink_ext_ack
*extack
)
300 struct nf_osf_user_finger
*f
;
301 struct nf_osf_finger
*kf
= NULL
, *sf
;
304 if (!capable(CAP_NET_ADMIN
))
307 if (!osf_attrs
[OSF_ATTR_FINGER
])
310 if (!(nlh
->nlmsg_flags
& NLM_F_CREATE
))
313 f
= nla_data(osf_attrs
[OSF_ATTR_FINGER
]);
315 kf
= kmalloc(sizeof(struct nf_osf_finger
), GFP_KERNEL
);
319 memcpy(&kf
->finger
, f
, sizeof(struct nf_osf_user_finger
));
321 list_for_each_entry(sf
, &nf_osf_fingers
[!!f
->df
], finger_entry
) {
322 if (memcmp(&sf
->finger
, f
, sizeof(struct nf_osf_user_finger
)))
328 if (nlh
->nlmsg_flags
& NLM_F_EXCL
)
334 * We are protected by nfnl mutex.
337 list_add_tail_rcu(&kf
->finger_entry
, &nf_osf_fingers
[!!f
->df
]);
342 static int nfnl_osf_remove_callback(struct net
*net
, struct sock
*ctnl
,
344 const struct nlmsghdr
*nlh
,
345 const struct nlattr
* const osf_attrs
[],
346 struct netlink_ext_ack
*extack
)
348 struct nf_osf_user_finger
*f
;
349 struct nf_osf_finger
*sf
;
352 if (!capable(CAP_NET_ADMIN
))
355 if (!osf_attrs
[OSF_ATTR_FINGER
])
358 f
= nla_data(osf_attrs
[OSF_ATTR_FINGER
]);
360 list_for_each_entry(sf
, &nf_osf_fingers
[!!f
->df
], finger_entry
) {
361 if (memcmp(&sf
->finger
, f
, sizeof(struct nf_osf_user_finger
)))
365 * We are protected by nfnl mutex.
367 list_del_rcu(&sf
->finger_entry
);
368 kfree_rcu(sf
, rcu_head
);
377 static const struct nfnl_callback nfnl_osf_callbacks
[OSF_MSG_MAX
] = {
379 .call
= nfnl_osf_add_callback
,
380 .attr_count
= OSF_ATTR_MAX
,
381 .policy
= nfnl_osf_policy
,
384 .call
= nfnl_osf_remove_callback
,
385 .attr_count
= OSF_ATTR_MAX
,
386 .policy
= nfnl_osf_policy
,
390 static const struct nfnetlink_subsystem nfnl_osf_subsys
= {
392 .subsys_id
= NFNL_SUBSYS_OSF
,
393 .cb_count
= OSF_MSG_MAX
,
394 .cb
= nfnl_osf_callbacks
,
397 static int __init
nfnl_osf_init(void)
402 for (i
= 0; i
< ARRAY_SIZE(nf_osf_fingers
); ++i
)
403 INIT_LIST_HEAD(&nf_osf_fingers
[i
]);
405 err
= nfnetlink_subsys_register(&nfnl_osf_subsys
);
407 pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err
);
416 static void __exit
nfnl_osf_fini(void)
418 struct nf_osf_finger
*f
;
421 nfnetlink_subsys_unregister(&nfnl_osf_subsys
);
424 for (i
= 0; i
< ARRAY_SIZE(nf_osf_fingers
); ++i
) {
425 list_for_each_entry_rcu(f
, &nf_osf_fingers
[i
], finger_entry
) {
426 list_del_rcu(&f
->finger_entry
);
427 kfree_rcu(f
, rcu_head
);
435 module_init(nfnl_osf_init
);
436 module_exit(nfnl_osf_fini
);
438 MODULE_LICENSE("GPL");