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
,
170 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
;
209 memset(&ctx
, 0, sizeof(ctx
));
211 tcp
= nf_osf_hdr_ctx_init(&ctx
, skb
, ip
, opts
);
215 ttl_check
= (info
->flags
& NF_OSF_TTL
) ? info
->ttl
: 0;
217 list_for_each_entry_rcu(kf
, &nf_osf_fingers
[ctx
.df
], finger_entry
) {
221 if (!(info
->flags
& NF_OSF_LOG
) && strcmp(info
->genre
, f
->genre
))
224 if (!nf_osf_match_one(skb
, f
, ttl_check
, &ctx
))
231 if (info
->flags
& NF_OSF_LOG
)
232 nf_log_packet(net
, family
, hooknum
, skb
,
234 "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
235 f
->genre
, f
->version
, f
->subtype
,
236 &ip
->saddr
, ntohs(tcp
->source
),
237 &ip
->daddr
, ntohs(tcp
->dest
),
240 if ((info
->flags
& NF_OSF_LOG
) &&
241 info
->loglevel
== NF_OSF_LOGLEVEL_FIRST
)
245 if (!fcount
&& (info
->flags
& NF_OSF_LOG
))
246 nf_log_packet(net
, family
, hooknum
, skb
, in
, out
, NULL
,
247 "Remote OS is not known: %pI4:%u -> %pI4:%u\n",
248 &ip
->saddr
, ntohs(tcp
->source
),
249 &ip
->daddr
, ntohs(tcp
->dest
));
254 return fmatch
== FMATCH_OK
;
256 EXPORT_SYMBOL_GPL(nf_osf_match
);
258 bool nf_osf_find(const struct sk_buff
*skb
,
259 const struct list_head
*nf_osf_fingers
,
260 const int ttl_check
, struct nf_osf_data
*data
)
262 const struct iphdr
*ip
= ip_hdr(skb
);
263 const struct nf_osf_user_finger
*f
;
264 unsigned char opts
[MAX_IPOPTLEN
];
265 const struct nf_osf_finger
*kf
;
266 struct nf_osf_hdr_ctx ctx
;
267 const struct tcphdr
*tcp
;
269 memset(&ctx
, 0, sizeof(ctx
));
271 tcp
= nf_osf_hdr_ctx_init(&ctx
, skb
, ip
, opts
);
275 list_for_each_entry_rcu(kf
, &nf_osf_fingers
[ctx
.df
], finger_entry
) {
277 if (!nf_osf_match_one(skb
, f
, ttl_check
, &ctx
))
280 data
->genre
= f
->genre
;
281 data
->version
= f
->version
;
287 EXPORT_SYMBOL_GPL(nf_osf_find
);
289 static const struct nla_policy nfnl_osf_policy
[OSF_ATTR_MAX
+ 1] = {
290 [OSF_ATTR_FINGER
] = { .len
= sizeof(struct nf_osf_user_finger
) },
293 static int nfnl_osf_add_callback(struct net
*net
, struct sock
*ctnl
,
294 struct sk_buff
*skb
, const struct nlmsghdr
*nlh
,
295 const struct nlattr
* const osf_attrs
[],
296 struct netlink_ext_ack
*extack
)
298 struct nf_osf_user_finger
*f
;
299 struct nf_osf_finger
*kf
= NULL
, *sf
;
302 if (!capable(CAP_NET_ADMIN
))
305 if (!osf_attrs
[OSF_ATTR_FINGER
])
308 if (!(nlh
->nlmsg_flags
& NLM_F_CREATE
))
311 f
= nla_data(osf_attrs
[OSF_ATTR_FINGER
]);
313 kf
= kmalloc(sizeof(struct nf_osf_finger
), GFP_KERNEL
);
317 memcpy(&kf
->finger
, f
, sizeof(struct nf_osf_user_finger
));
319 list_for_each_entry(sf
, &nf_osf_fingers
[!!f
->df
], finger_entry
) {
320 if (memcmp(&sf
->finger
, f
, sizeof(struct nf_osf_user_finger
)))
326 if (nlh
->nlmsg_flags
& NLM_F_EXCL
)
332 * We are protected by nfnl mutex.
335 list_add_tail_rcu(&kf
->finger_entry
, &nf_osf_fingers
[!!f
->df
]);
340 static int nfnl_osf_remove_callback(struct net
*net
, struct sock
*ctnl
,
342 const struct nlmsghdr
*nlh
,
343 const struct nlattr
* const osf_attrs
[],
344 struct netlink_ext_ack
*extack
)
346 struct nf_osf_user_finger
*f
;
347 struct nf_osf_finger
*sf
;
350 if (!capable(CAP_NET_ADMIN
))
353 if (!osf_attrs
[OSF_ATTR_FINGER
])
356 f
= nla_data(osf_attrs
[OSF_ATTR_FINGER
]);
358 list_for_each_entry(sf
, &nf_osf_fingers
[!!f
->df
], finger_entry
) {
359 if (memcmp(&sf
->finger
, f
, sizeof(struct nf_osf_user_finger
)))
363 * We are protected by nfnl mutex.
365 list_del_rcu(&sf
->finger_entry
);
366 kfree_rcu(sf
, rcu_head
);
375 static const struct nfnl_callback nfnl_osf_callbacks
[OSF_MSG_MAX
] = {
377 .call
= nfnl_osf_add_callback
,
378 .attr_count
= OSF_ATTR_MAX
,
379 .policy
= nfnl_osf_policy
,
382 .call
= nfnl_osf_remove_callback
,
383 .attr_count
= OSF_ATTR_MAX
,
384 .policy
= nfnl_osf_policy
,
388 static const struct nfnetlink_subsystem nfnl_osf_subsys
= {
390 .subsys_id
= NFNL_SUBSYS_OSF
,
391 .cb_count
= OSF_MSG_MAX
,
392 .cb
= nfnl_osf_callbacks
,
395 static int __init
nfnl_osf_init(void)
400 for (i
= 0; i
< ARRAY_SIZE(nf_osf_fingers
); ++i
)
401 INIT_LIST_HEAD(&nf_osf_fingers
[i
]);
403 err
= nfnetlink_subsys_register(&nfnl_osf_subsys
);
405 pr_err("Failed to register OSF nsfnetlink helper (%d)\n", err
);
414 static void __exit
nfnl_osf_fini(void)
416 struct nf_osf_finger
*f
;
419 nfnetlink_subsys_unregister(&nfnl_osf_subsys
);
422 for (i
= 0; i
< ARRAY_SIZE(nf_osf_fingers
); ++i
) {
423 list_for_each_entry_rcu(f
, &nf_osf_fingers
[i
], finger_entry
) {
424 list_del_rcu(&f
->finger_entry
);
425 kfree_rcu(f
, rcu_head
);
433 module_init(nfnl_osf_init
);
434 module_exit(nfnl_osf_fini
);
436 MODULE_LICENSE("GPL");