History

netfilter: extract Passive OS fingerprint infrastructure from xt_osf

Add nf_osf_ttl() and nf_osf_match() into nf_osf.c to prepare for nf_tables support.

Fernando Fernandez Mancera committed 8 years ago

Commit bfb15f21 parent 3f9c56a7 files · +359 −289Browse files

Unified · Split

7 files
  1. include/linux/netfilter/nf_osf.h +27 −0
  2. include/uapi/linux/netfilter/nf_osf.h +90 −0
  3. include/uapi/linux/netfilter/xt_osf.h +17 −89
  4. net/netfilter/Kconfig +4 −0
  5. net/netfilter/Makefile +1 −0
  6. net/netfilter/nf_osf.c +218 −0
  7. net/netfilter/xt_osf.c +2 −200
include/linux/netfilter/nf_osf.h+27−0
@@ -0,0 +1,27 @@
1+#include <uapi/linux/netfilter/nf_osf.h>
2+
3+/* Initial window size option state machine: multiple of mss, mtu or
4+ * plain numeric value. Can also be made as plain numeric value which
5+ * is not a multiple of specified value.
6+ */
7+enum nf_osf_window_size_options {
8+ OSF_WSS_PLAIN = 0,
9+ OSF_WSS_MSS,
10+ OSF_WSS_MTU,
11+ OSF_WSS_MODULO,
12+ OSF_WSS_MAX,
13+};
14+
15+enum osf_fmatch_states {
16+ /* Packet does not match the fingerprint */
17+ FMATCH_WRONG = 0,
18+ /* Packet matches the fingerprint */
19+ FMATCH_OK,
20+ /* Options do not match the fingerprint, but header does */
21+ FMATCH_OPT_WRONG,
22+};
23+
24+bool nf_osf_match(const struct sk_buff *skb, u_int8_t family,
25+ int hooknum, struct net_device *in, struct net_device *out,
26+ const struct nf_osf_info *info, struct net *net,
27+ const struct list_head *nf_osf_fingers);
include/uapi/linux/netfilter/nf_osf.h+90−0
@@ -0,0 +1,90 @@
1+#ifndef _NF_OSF_H
2+#define _NF_OSF_H
3+
4+#define MAXGENRELEN 32
5+
6+#define NF_OSF_GENRE (1 << 0)
7+#define NF_OSF_TTL (1 << 1)
8+#define NF_OSF_LOG (1 << 2)
9+#define NF_OSF_INVERT (1 << 3)
10+
11+#define NF_OSF_LOGLEVEL_ALL 0 /* log all matched fingerprints */
12+#define NF_OSF_LOGLEVEL_FIRST 1 /* log only the first matced fingerprint */
13+#define NF_OSF_LOGLEVEL_ALL_KNOWN 2 /* do not log unknown packets */
14+
15+#define NF_OSF_TTL_TRUE 0 /* True ip and fingerprint TTL comparison */
16+
17+/* Do not compare ip and fingerprint TTL at all */
18+#define NF_OSF_TTL_NOCHECK 2
19+
20+/* Wildcard MSS (kind of).
21+ * It is used to implement a state machine for the different wildcard values
22+ * of the MSS and window sizes.
23+ */
24+struct nf_osf_wc {
25+ __u32 wc;
26+ __u32 val;
27+};
28+
29+/* This struct represents IANA options
30+ * http://www.iana.org/assignments/tcp-parameters
31+ */
32+struct nf_osf_opt {
33+ __u16 kind, length;
34+ struct nf_osf_wc wc;
35+};
36+
37+struct nf_osf_info {
38+ char genre[MAXGENRELEN];
39+ __u32 len;
40+ __u32 flags;
41+ __u32 loglevel;
42+ __u32 ttl;
43+};
44+
45+struct nf_osf_user_finger {
46+ struct nf_osf_wc wss;
47+
48+ __u8 ttl, df;
49+ __u16 ss, mss;
50+ __u16 opt_num;
51+
52+ char genre[MAXGENRELEN];
53+ char version[MAXGENRELEN];
54+ char subtype[MAXGENRELEN];
55+
56+ /* MAX_IPOPTLEN is maximum if all options are NOPs or EOLs */
57+ struct nf_osf_opt opt[MAX_IPOPTLEN];
58+};
59+
60+struct nf_osf_finger {
61+ struct rcu_head rcu_head;
62+ struct list_head finger_entry;
63+ struct nf_osf_user_finger finger;
64+};
65+
66+struct nf_osf_nlmsg {
67+ struct nf_osf_user_finger f;
68+ struct iphdr ip;
69+ struct tcphdr tcp;
70+};
71+
72+/* Defines for IANA option kinds */
73+enum iana_options {
74+ OSFOPT_EOL = 0, /* End of options */
75+ OSFOPT_NOP, /* NOP */
76+ OSFOPT_MSS, /* Maximum segment size */
77+ OSFOPT_WSO, /* Window scale option */
78+ OSFOPT_SACKP, /* SACK permitted */
79+ OSFOPT_SACK, /* SACK */
80+ OSFOPT_ECHO,
81+ OSFOPT_ECHOREPLY,
82+ OSFOPT_TS, /* Timestamp option */
83+ OSFOPT_POCP, /* Partial Order Connection Permitted */
84+ OSFOPT_POSP, /* Partial Order Service Profile */
85+
86+ /* Others are not used in the current OSF */
87+ OSFOPT_EMPTY = 255,
88+};
89+
90+#endif /* _NF_OSF_H */
include/uapi/linux/netfilter/xt_osf.h+17−89
@@ -23,101 +23,29 @@ · 22 unmodified lines
2323 #include <linux/types.h>
2424 #include <linux/ip.h>
2525 #include <linux/tcp.h>
26+#include <linux/netfilter/nf_osf.h>
2627
27−#define MAXGENRELEN 32
28+#define XT_OSF_GENRE NF_OSF_GENRE
29+#define XT_OSF_INVERT NF_OSF_INVERT
2830
29−#define XT_OSF_GENRE (1<<0)
30−#define XT_OSF_TTL (1<<1)
31−#define XT_OSF_LOG (1<<2)
32−#define XT_OSF_INVERT (1<<3)
31+#define XT_OSF_TTL NF_OSF_TTL
32+#define XT_OSF_LOG NF_OSF_LOG
3333
34−#define XT_OSF_LOGLEVEL_ALL 0 /* log all matched fingerprints */
35−#define XT_OSF_LOGLEVEL_FIRST 1 /* log only the first matced fingerprint */
36−#define XT_OSF_LOGLEVEL_ALL_KNOWN 2 /* do not log unknown packets */
34+#define XT_OSF_LOGLEVEL_ALL NF_OSF_LOGLEVEL_ALL
35+#define XT_OSF_LOGLEVEL_FIRST NF_OSF_LOGLEVEL_FIRST
36+#define XT_OSF_LOGLEVEL_ALL_KNOWN NF_OSF_LOGLEVEL_ALL_KNOWN
3737
38−#define XT_OSF_TTL_TRUE 0 /* True ip and fingerprint TTL comparison */
39−#define XT_OSF_TTL_LESS 1 /* Check if ip TTL is less than fingerprint one */
40−#define XT_OSF_TTL_NOCHECK 2 /* Do not compare ip and fingerprint TTL at all */
38+#define XT_OSF_TTL_TRUE NF_OSF_TTL_TRUE
39+#define XT_OSF_TTL_NOCHECK NF_OSF_TTL_NOCHECK
4140
42−struct xt_osf_info {
43− char genre[MAXGENRELEN];
44− __u32 len;
45− __u32 flags;
46− __u32 loglevel;
47− __u32 ttl;
48−};
49−
50−/*
51− * Wildcard MSS (kind of).
52− * It is used to implement a state machine for the different wildcard values
53− * of the MSS and window sizes.
54− */
55−struct xt_osf_wc {
56− __u32 wc;
57− __u32 val;
58−};
59−
60−/*
61− * This struct represents IANA options
62− * http://www.iana.org/assignments/tcp-parameters
63− */
64−struct xt_osf_opt {
65− __u16 kind, length;
66− struct xt_osf_wc wc;
67−};
68−
69−struct xt_osf_user_finger {
70− struct xt_osf_wc wss;
71−
72− __u8 ttl, df;
73− __u16 ss, mss;
74− __u16 opt_num;
75−
76− char genre[MAXGENRELEN];
77− char version[MAXGENRELEN];
78− char subtype[MAXGENRELEN];
41+#define XT_OSF_TTL_LESS 1 /* Check if ip TTL is less than fingerprint one */
7942
80− /* MAX_IPOPTLEN is maximum if all options are NOPs or EOLs */
81− struct xt_osf_opt opt[MAX_IPOPTLEN];
82−};
83−
84−struct xt_osf_nlmsg {
85− struct xt_osf_user_finger f;
86− struct iphdr ip;
87− struct tcphdr tcp;
88−};
89−
90−/* Defines for IANA option kinds */
91−
92−enum iana_options {
93− OSFOPT_EOL = 0, /* End of options */
94− OSFOPT_NOP, /* NOP */
95− OSFOPT_MSS, /* Maximum segment size */
96− OSFOPT_WSO, /* Window scale option */
97− OSFOPT_SACKP, /* SACK permitted */
98− OSFOPT_SACK, /* SACK */
99− OSFOPT_ECHO,
100− OSFOPT_ECHOREPLY,
101− OSFOPT_TS, /* Timestamp option */
102− OSFOPT_POCP, /* Partial Order Connection Permitted */
103− OSFOPT_POSP, /* Partial Order Service Profile */
104−
105− /* Others are not used in the current OSF */
106− OSFOPT_EMPTY = 255,
107−};
108−
109−/*
110− * Initial window size option state machine: multiple of mss, mtu or
111− * plain numeric value. Can also be made as plain numeric value which
112− * is not a multiple of specified value.
113− */
114−enum xt_osf_window_size_options {
115− OSF_WSS_PLAIN = 0,
116− OSF_WSS_MSS,
117− OSF_WSS_MTU,
118− OSF_WSS_MODULO,
119− OSF_WSS_MAX,
120−};
43+#define xt_osf_wc nf_osf_wc
44+#define xt_osf_opt nf_osf_opt
45+#define xt_osf_info nf_osf_info
46+#define xt_osf_user_finger nf_osf_user_finger
47+#define xt_osf_finger nf_osf_finger
48+#define xt_osf_nlmsg nf_osf_nlmsg
12149
12250 /*
12351 * Add/remove fingerprint from the kernel.
net/netfilter/Kconfig+4−0
@@ -444,6 +444,9 @@ config NETFILTER_SYNPROXY · 443 unmodified lines
444444
445445 endif # NF_CONNTRACK
446446
447+config NF_OSF
448+ tristate 'Passive OS fingerprint infrastructure'
449+
447450 config NF_TABLES
448451 select NETFILTER_NETLINK
449452 tristate "Netfilter nf_tables support"
@@ -1358,6 +1361,7 @@ config NETFILTER_XT_MATCH_NFACCT · 908 unmodified lines
13581361 config NETFILTER_XT_MATCH_OSF
13591362 tristate '"osf" Passive OS fingerprint match'
13601363 depends on NETFILTER_ADVANCED && NETFILTER_NETLINK
1364+ select NF_OSF
13611365 help
13621366 This option selects the Passive OS Fingerprinting match module
13631367 that allows to passively match the remote operating system by
net/netfilter/Makefile+1−0
@@ -101,6 +101,7 @@ obj-$(CONFIG_NFT_HASH) += nft_hash.o · 100 unmodified lines
101101 obj-$(CONFIG_NFT_FIB) += nft_fib.o
102102 obj-$(CONFIG_NFT_FIB_INET) += nft_fib_inet.o
103103 obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o
104+obj-$(CONFIG_NF_OSF) += nf_osf.o
104105
105106 # nf_tables netdev
106107 obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
net/netfilter/nf_osf.c+218−0
@@ -0,0 +1,218 @@
1+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2+#include <linux/module.h>
3+#include <linux/kernel.h>
4+
5+#include <linux/capability.h>
6+#include <linux/if.h>
7+#include <linux/inetdevice.h>
8+#include <linux/ip.h>
9+#include <linux/list.h>
10+#include <linux/rculist.h>
11+#include <linux/skbuff.h>
12+#include <linux/slab.h>
13+#include <linux/tcp.h>
14+
15+#include <net/ip.h>
16+#include <net/tcp.h>
17+
18+#include <linux/netfilter/nfnetlink.h>
19+#include <linux/netfilter/x_tables.h>
20+#include <net/netfilter/nf_log.h>
21+#include <linux/netfilter/nf_osf.h>
22+
23+static inline int nf_osf_ttl(const struct sk_buff *skb,
24+ const struct nf_osf_info *info,
25+ unsigned char f_ttl)
26+{
27+ const struct iphdr *ip = ip_hdr(skb);
28+
29+ if (info->flags & NF_OSF_TTL) {
30+ if (info->ttl == NF_OSF_TTL_TRUE)
31+ return ip->ttl == f_ttl;
32+ if (info->ttl == NF_OSF_TTL_NOCHECK)
33+ return 1;
34+ else if (ip->ttl <= f_ttl)
35+ return 1;
36+ else {
37+ struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
38+ int ret = 0;
39+
40+ for_ifa(in_dev) {
41+ if (inet_ifa_match(ip->saddr, ifa)) {
42+ ret = (ip->ttl == f_ttl);
43+ break;
44+ }
45+ }
46+ endfor_ifa(in_dev);
47+
48+ return ret;
49+ }
50+ }
51+
52+ return ip->ttl == f_ttl;
53+}
54+
55+bool
56+nf_osf_match(const struct sk_buff *skb, u_int8_t family,
57+ int hooknum, struct net_device *in, struct net_device *out,
58+ const struct nf_osf_info *info, struct net *net,
59+ const struct list_head *nf_osf_fingers)
60+{
61+ const unsigned char *optp = NULL, *_optp = NULL;
62+ unsigned int optsize = 0, check_WSS = 0;
63+ int fmatch = FMATCH_WRONG, fcount = 0;
64+ const struct iphdr *ip = ip_hdr(skb);
65+ const struct nf_osf_user_finger *f;
66+ unsigned char opts[MAX_IPOPTLEN];
67+ const struct nf_osf_finger *kf;
68+ u16 window, totlen, mss = 0;
69+ const struct tcphdr *tcp;
70+ struct tcphdr _tcph;
71+ bool df;
72+
73+ tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph);
74+ if (!tcp)
75+ return false;
76+
77+ if (!tcp->syn)
78+ return false;
79+
80+ totlen = ntohs(ip->tot_len);
81+ df = ntohs(ip->frag_off) & IP_DF;
82+ window = ntohs(tcp->window);
83+
84+ if (tcp->doff * 4 > sizeof(struct tcphdr)) {
85+ optsize = tcp->doff * 4 - sizeof(struct tcphdr);
86+
87+ _optp = optp = skb_header_pointer(skb, ip_hdrlen(skb) +
88+ sizeof(struct tcphdr), optsize, opts);
89+ }
90+
91+ list_for_each_entry_rcu(kf, &nf_osf_fingers[df], finger_entry) {
92+ int foptsize, optnum;
93+
94+ f = &kf->finger;
95+
96+ if (!(info->flags & NF_OSF_LOG) && strcmp(info->genre, f->genre))
97+ continue;
98+
99+ optp = _optp;
100+ fmatch = FMATCH_WRONG;
101+
102+ if (totlen != f->ss || !nf_osf_ttl(skb, info, f->ttl))
103+ continue;
104+
105+ /*
106+ * Should not happen if userspace parser was written correctly.
107+ */
108+ if (f->wss.wc >= OSF_WSS_MAX)
109+ continue;
110+
111+ /* Check options */
112+
113+ foptsize = 0;
114+ for (optnum = 0; optnum < f->opt_num; ++optnum)
115+ foptsize += f->opt[optnum].length;
116+
117+ if (foptsize > MAX_IPOPTLEN ||
118+ optsize > MAX_IPOPTLEN ||
119+ optsize != foptsize)
120+ continue;
121+
122+ check_WSS = f->wss.wc;
123+
124+ for (optnum = 0; optnum < f->opt_num; ++optnum) {
125+ if (f->opt[optnum].kind == (*optp)) {
126+ __u32 len = f->opt[optnum].length;
127+ const __u8 *optend = optp + len;
128+
129+ fmatch = FMATCH_OK;
130+
131+ switch (*optp) {
132+ case OSFOPT_MSS:
133+ mss = optp[3];
134+ mss <<= 8;
135+ mss |= optp[2];
136+
137+ mss = ntohs((__force __be16)mss);
138+ break;
139+ case OSFOPT_TS:
140+ break;
141+ }
142+
143+ optp = optend;
144+ } else
145+ fmatch = FMATCH_OPT_WRONG;
146+
147+ if (fmatch != FMATCH_OK)
148+ break;
149+ }
150+
151+ if (fmatch != FMATCH_OPT_WRONG) {
152+ fmatch = FMATCH_WRONG;
153+
154+ switch (check_WSS) {
155+ case OSF_WSS_PLAIN:
156+ if (f->wss.val == 0 || window == f->wss.val)
157+ fmatch = FMATCH_OK;
158+ break;
159+ case OSF_WSS_MSS:
160+ /*
161+ * Some smart modems decrease mangle MSS to
162+ * SMART_MSS_2, so we check standard, decreased
163+ * and the one provided in the fingerprint MSS
164+ * values.
165+ */
166+#define SMART_MSS_1 1460
167+#define SMART_MSS_2 1448
168+ if (window == f->wss.val * mss ||
169+ window == f->wss.val * SMART_MSS_1 ||
170+ window == f->wss.val * SMART_MSS_2)
171+ fmatch = FMATCH_OK;
172+ break;
173+ case OSF_WSS_MTU:
174+ if (window == f->wss.val * (mss + 40) ||
175+ window == f->wss.val * (SMART_MSS_1 + 40) ||
176+ window == f->wss.val * (SMART_MSS_2 + 40))
177+ fmatch = FMATCH_OK;
178+ break;
179+ case OSF_WSS_MODULO:
180+ if ((window % f->wss.val) == 0)
181+ fmatch = FMATCH_OK;
182+ break;
183+ }
184+ }
185+
186+ if (fmatch != FMATCH_OK)
187+ continue;
188+
189+ fcount++;
190+
191+ if (info->flags & NF_OSF_LOG)
192+ nf_log_packet(net, family, hooknum, skb,
193+ in, out, NULL,
194+ "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
195+ f->genre, f->version, f->subtype,
196+ &ip->saddr, ntohs(tcp->source),
197+ &ip->daddr, ntohs(tcp->dest),
198+ f->ttl - ip->ttl);
199+
200+ if ((info->flags & NF_OSF_LOG) &&
201+ info->loglevel == NF_OSF_LOGLEVEL_FIRST)
202+ break;
203+ }
204+
205+ if (!fcount && (info->flags & NF_OSF_LOG))
206+ nf_log_packet(net, family, hooknum, skb, in, out, NULL,
207+ "Remote OS is not known: %pI4:%u -> %pI4:%u\n",
208+ &ip->saddr, ntohs(tcp->source),
209+ &ip->daddr, ntohs(tcp->dest));
210+
211+ if (fcount)
212+ fmatch = FMATCH_OK;
213+
214+ return fmatch == FMATCH_OK;
215+}
216+EXPORT_SYMBOL_GPL(nf_osf_match);
217+
218+MODULE_LICENSE("GPL");
net/netfilter/xt_osf.c+2−200
@@ -37,21 +37,6 @@ · 36 unmodified lines
3737 #include <net/netfilter/nf_log.h>
3838 #include <linux/netfilter/xt_osf.h>
3939
40−struct xt_osf_finger {
41− struct rcu_head rcu_head;
42− struct list_head finger_entry;
43− struct xt_osf_user_finger finger;
44−};
45−
46−enum osf_fmatch_states {
47− /* Packet does not match the fingerprint */
48− FMATCH_WRONG = 0,
49− /* Packet matches the fingerprint */
50− FMATCH_OK,
51− /* Options do not match the fingerprint, but header does */
52− FMATCH_OPT_WRONG,
53−};
54−
5540 /*
5641 * Indexed by dont-fragment bit.
5742 * It is the only constant value in the fingerprint.
@@ -164,200 +149,17 @@ static const struct nfnetlink_subsystem xt_osf_nfnetlink = { · 106 unmodified lines
164149 .cb = xt_osf_nfnetlink_callbacks,
165150 };
166151
167−static inline int xt_osf_ttl(const struct sk_buff *skb, const struct xt_osf_info *info,
168− unsigned char f_ttl)
169−{
170− const struct iphdr *ip = ip_hdr(skb);
171−
172− if (info->flags & XT_OSF_TTL) {
173− if (info->ttl == XT_OSF_TTL_TRUE)
174− return ip->ttl == f_ttl;
175− if (info->ttl == XT_OSF_TTL_NOCHECK)
176− return 1;
177− else if (ip->ttl <= f_ttl)
178− return 1;
179− else {
180− struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
181− int ret = 0;
182−
183− for_ifa(in_dev) {
184− if (inet_ifa_match(ip->saddr, ifa)) {
185− ret = (ip->ttl == f_ttl);
186− break;
187− }
188− }
189− endfor_ifa(in_dev);
190−
191− return ret;
192− }
193− }
194−
195− return ip->ttl == f_ttl;
196−}
197−
198152 static bool
199153 xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p)
200154 {
201155 const struct xt_osf_info *info = p->matchinfo;
202− const struct iphdr *ip = ip_hdr(skb);
203− const struct tcphdr *tcp;
204− struct tcphdr _tcph;
205− int fmatch = FMATCH_WRONG, fcount = 0;
206− unsigned int optsize = 0, check_WSS = 0;
207− u16 window, totlen, mss = 0;
208− bool df;
209− const unsigned char *optp = NULL, *_optp = NULL;
210− unsigned char opts[MAX_IPOPTLEN];
211− const struct xt_osf_finger *kf;
212− const struct xt_osf_user_finger *f;
213156 struct net *net = xt_net(p);
214157
215158 if (!info)
216159 return false;
217160
218− tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph);
219− if (!tcp)
220− return false;
221−
222− if (!tcp->syn)
223− return false;
224−
225− totlen = ntohs(ip->tot_len);
226− df = ntohs(ip->frag_off) & IP_DF;
227− window = ntohs(tcp->window);
228−
229− if (tcp->doff * 4 > sizeof(struct tcphdr)) {
230− optsize = tcp->doff * 4 - sizeof(struct tcphdr);
231−
232− _optp = optp = skb_header_pointer(skb, ip_hdrlen(skb) +
233− sizeof(struct tcphdr), optsize, opts);
234− }
235−
236− list_for_each_entry_rcu(kf, &xt_osf_fingers[df], finger_entry) {
237− int foptsize, optnum;
238−
239− f = &kf->finger;
240−
241− if (!(info->flags & XT_OSF_LOG) && strcmp(info->genre, f->genre))
242− continue;
243−
244− optp = _optp;
245− fmatch = FMATCH_WRONG;
246−
247− if (totlen != f->ss || !xt_osf_ttl(skb, info, f->ttl))
248− continue;
249−
250− /*
251− * Should not happen if userspace parser was written correctly.
252− */
253− if (f->wss.wc >= OSF_WSS_MAX)
254− continue;
255−
256− /* Check options */
257−
258− foptsize = 0;
259− for (optnum = 0; optnum < f->opt_num; ++optnum)
260− foptsize += f->opt[optnum].length;
261−
262− if (foptsize > MAX_IPOPTLEN ||
263− optsize > MAX_IPOPTLEN ||
264− optsize != foptsize)
265− continue;
266−
267− check_WSS = f->wss.wc;
268−
269− for (optnum = 0; optnum < f->opt_num; ++optnum) {
270− if (f->opt[optnum].kind == (*optp)) {
271− __u32 len = f->opt[optnum].length;
272− const __u8 *optend = optp + len;
273−
274− fmatch = FMATCH_OK;
275−
276− switch (*optp) {
277− case OSFOPT_MSS:
278− mss = optp[3];
279− mss <<= 8;
280− mss |= optp[2];
281−
282− mss = ntohs((__force __be16)mss);
283− break;
284− case OSFOPT_TS:
285− break;
286− }
287−
288− optp = optend;
289− } else
290− fmatch = FMATCH_OPT_WRONG;
291−
292− if (fmatch != FMATCH_OK)
293− break;
294− }
295−
296− if (fmatch != FMATCH_OPT_WRONG) {
297− fmatch = FMATCH_WRONG;
298−
299− switch (check_WSS) {
300− case OSF_WSS_PLAIN:
301− if (f->wss.val == 0 || window == f->wss.val)
302− fmatch = FMATCH_OK;
303− break;
304− case OSF_WSS_MSS:
305− /*
306− * Some smart modems decrease mangle MSS to
307− * SMART_MSS_2, so we check standard, decreased
308− * and the one provided in the fingerprint MSS
309− * values.
310− */
311−#define SMART_MSS_1 1460
312−#define SMART_MSS_2 1448
313− if (window == f->wss.val * mss ||
314− window == f->wss.val * SMART_MSS_1 ||
315− window == f->wss.val * SMART_MSS_2)
316− fmatch = FMATCH_OK;
317− break;
318− case OSF_WSS_MTU:
319− if (window == f->wss.val * (mss + 40) ||
320− window == f->wss.val * (SMART_MSS_1 + 40) ||
321− window == f->wss.val * (SMART_MSS_2 + 40))
322− fmatch = FMATCH_OK;
323− break;
324− case OSF_WSS_MODULO:
325− if ((window % f->wss.val) == 0)
326− fmatch = FMATCH_OK;
327− break;
328− }
329− }
330−
331− if (fmatch != FMATCH_OK)
332− continue;
333−
334− fcount++;
335−
336− if (info->flags & XT_OSF_LOG)
337− nf_log_packet(net, xt_family(p), xt_hooknum(p), skb,
338− xt_in(p), xt_out(p), NULL,
339− "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
340− f->genre, f->version, f->subtype,
341− &ip->saddr, ntohs(tcp->source),
342− &ip->daddr, ntohs(tcp->dest),
343− f->ttl - ip->ttl);
344−
345− if ((info->flags & XT_OSF_LOG) &&
346− info->loglevel == XT_OSF_LOGLEVEL_FIRST)
347− break;
348− }
349−
350− if (!fcount && (info->flags & XT_OSF_LOG))
351− nf_log_packet(net, xt_family(p), xt_hooknum(p), skb, xt_in(p),
352− xt_out(p), NULL,
353− "Remote OS is not known: %pI4:%u -> %pI4:%u\n",
354− &ip->saddr, ntohs(tcp->source),
355− &ip->daddr, ntohs(tcp->dest));
356−
357− if (fcount)
358− fmatch = FMATCH_OK;
359−
360− return fmatch == FMATCH_OK;
161+ return nf_osf_match(skb, xt_family(p), xt_hooknum(p), xt_in(p),
162+ xt_out(p), info, net, xt_osf_fingers);
361163 }
362164
363165 static struct xt_match xt_osf_match = {