Deleted Added
full compact
pf_osfp.c (223637) pf_osfp.c (240233)
1/* $OpenBSD: pf_osfp.c,v 1.14 2008/06/12 18:17:01 henning Exp $ */
2
3/*
4 * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
1/* $OpenBSD: pf_osfp.c,v 1.14 2008/06/12 18:17:01 henning Exp $ */
2
3/*
4 * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20#ifdef __FreeBSD__
21#include <sys/cdefs.h>
20#include <sys/cdefs.h>
22__FBSDID("$FreeBSD: head/sys/contrib/pf/net/pf_osfp.c 223637 2011-06-28 11:57:25Z bz $");
23#endif
21__FBSDID("$FreeBSD: head/sys/contrib/pf/net/pf_osfp.c 240233 2012-09-08 06:41:54Z glebius $");
24
25#include <sys/param.h>
22
23#include <sys/param.h>
24#include <sys/kernel.h>
26#include <sys/socket.h>
25#include <sys/socket.h>
27#ifdef _KERNEL
28#include <sys/systm.h>
29#ifndef __FreeBSD__
30#include <sys/pool.h>
31#endif
32#endif /* _KERNEL */
33#include <sys/mbuf.h>
34
35#include <netinet/in.h>
26
27#include <netinet/in.h>
36#include <netinet/in_systm.h>
37#include <netinet/ip.h>
38#include <netinet/tcp.h>
39
40#include <net/if.h>
41#include <net/pfvar.h>
42
43#include <netinet/ip6.h>
28#include <netinet/ip.h>
29#include <netinet/tcp.h>
30
31#include <net/if.h>
32#include <net/pfvar.h>
33
34#include <netinet/ip6.h>
44#ifdef _KERNEL
45#include <netinet6/in6_var.h>
35#include <netinet6/in6_var.h>
46#endif
47
36
48
49#ifdef _KERNEL
50#ifdef __FreeBSD__
37static MALLOC_DEFINE(M_PFOSFP, "pf_osfp", "pf(4) operating system fingerprints");
51#define DPFPRINTF(format, x...) \
52 if (V_pf_status.debug >= PF_DEBUG_NOISY) \
53 printf(format , ##x)
38#define DPFPRINTF(format, x...) \
39 if (V_pf_status.debug >= PF_DEBUG_NOISY) \
40 printf(format , ##x)
54#else
55#define DPFPRINTF(format, x...) \
56 if (pf_status.debug >= PF_DEBUG_NOISY) \
57 printf(format , ##x)
58#endif
59#ifdef __FreeBSD__
60typedef uma_zone_t pool_t;
61#else
62typedef struct pool pool_t;
63#endif
64
41
65#else
66/* Userland equivalents so we can lend code to tcpdump et al. */
67
68#include <arpa/inet.h>
69#include <errno.h>
70#include <stdio.h>
71#include <stdlib.h>
72#include <string.h>
73#include <netdb.h>
74#define pool_t int
75#define pool_get(pool, flags) malloc(*(pool))
76#define pool_put(pool, item) free(item)
77#define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
78
79#ifdef __FreeBSD__
80#define NTOHS(x) (x) = ntohs((u_int16_t)(x))
81#endif
82
83#ifdef PFDEBUG
84#include <sys/stdarg.h>
85#define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
86#else
87#define DPFPRINTF(format, x...) ((void)0)
88#endif /* PFDEBUG */
89#endif /* _KERNEL */
90
91
92#ifdef __FreeBSD__
93SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
42SLIST_HEAD(pf_osfp_list, pf_os_fingerprint);
94VNET_DEFINE(struct pf_osfp_list, pf_osfp_list);
43static VNET_DEFINE(struct pf_osfp_list, pf_osfp_list) =
44 SLIST_HEAD_INITIALIZER();
95#define V_pf_osfp_list VNET(pf_osfp_list)
45#define V_pf_osfp_list VNET(pf_osfp_list)
96VNET_DEFINE(pool_t, pf_osfp_entry_pl);
97#define pf_osfp_entry_pl VNET(pf_osfp_entry_pl)
98VNET_DEFINE(pool_t, pf_osfp_pl);
99#define pf_osfp_pl VNET(pf_osfp_pl)
100#else
101SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
102pool_t pf_osfp_entry_pl;
103pool_t pf_osfp_pl;
104#endif
105
46
106struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
47static struct pf_osfp_enlist *pf_osfp_fingerprint_hdr(const struct ip *,
48 const struct ip6_hdr *,
49 const struct tcphdr *);
50static struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
107 struct pf_os_fingerprint *, u_int8_t);
51 struct pf_os_fingerprint *, u_int8_t);
108struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
52static struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
109 struct pf_os_fingerprint *);
53 struct pf_os_fingerprint *);
110void pf_osfp_insert(struct pf_osfp_list *,
54static void pf_osfp_insert(struct pf_osfp_list *,
111 struct pf_os_fingerprint *);
55 struct pf_os_fingerprint *);
56#ifdef PFDEBUG
57static struct pf_os_fingerprint *pf_osfp_validate(void);
58#endif
112
59
113
114#ifdef _KERNEL
115/*
116 * Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
117 * Returns the list of possible OSes.
118 */
119struct pf_osfp_enlist *
120pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
121 const struct tcphdr *tcp)
122{

--- 12 unchanged lines hidden (view full) ---

135 ip = (struct ip *)NULL;
136 ip6 = mtod(m, struct ip6_hdr *);
137 }
138 if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL,
139 pd->af)) return (NULL);
140
141 return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
142}
60/*
61 * Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
62 * Returns the list of possible OSes.
63 */
64struct pf_osfp_enlist *
65pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
66 const struct tcphdr *tcp)
67{

--- 12 unchanged lines hidden (view full) ---

80 ip = (struct ip *)NULL;
81 ip6 = mtod(m, struct ip6_hdr *);
82 }
83 if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL,
84 pd->af)) return (NULL);
85
86 return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
87}
143#endif /* _KERNEL */
144
88
145struct pf_osfp_enlist *
89static struct pf_osfp_enlist *
146pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
147{
148 struct pf_os_fingerprint fp, *fpresult;
149 int cnt, optlen = 0;
150 const u_int8_t *optp;
90pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
91{
92 struct pf_os_fingerprint fp, *fpresult;
93 int cnt, optlen = 0;
94 const u_int8_t *optp;
151#ifdef _KERNEL
152 char srcname[128];
95 char srcname[128];
153#else
154 char srcname[NI_MAXHOST];
155#endif
156
157 if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
158 return (NULL);
159 if (ip) {
160 if ((ip->ip_off & htons(IP_OFFMASK)) != 0)
161 return (NULL);
162 }
163
164 memset(&fp, 0, sizeof(fp));
165
166 if (ip) {
96
97 if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
98 return (NULL);
99 if (ip) {
100 if ((ip->ip_off & htons(IP_OFFMASK)) != 0)
101 return (NULL);
102 }
103
104 memset(&fp, 0, sizeof(fp));
105
106 if (ip) {
167#ifndef _KERNEL
168 struct sockaddr_in sin;
169#endif
170
171 fp.fp_psize = ntohs(ip->ip_len);
172 fp.fp_ttl = ip->ip_ttl;
173 if (ip->ip_off & htons(IP_DF))
174 fp.fp_flags |= PF_OSFP_DF;
107 fp.fp_psize = ntohs(ip->ip_len);
108 fp.fp_ttl = ip->ip_ttl;
109 if (ip->ip_off & htons(IP_DF))
110 fp.fp_flags |= PF_OSFP_DF;
175#ifdef _KERNEL
176 strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
111 strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
177#else
178 memset(&sin, 0, sizeof(sin));
179 sin.sin_family = AF_INET;
180 sin.sin_len = sizeof(struct sockaddr_in);
181 sin.sin_addr = ip->ip_src;
182 (void)getnameinfo((struct sockaddr *)&sin,
183 sizeof(struct sockaddr_in), srcname, sizeof(srcname),
184 NULL, 0, NI_NUMERICHOST);
185#endif
186 }
187#ifdef INET6
188 else if (ip6) {
112 }
113#ifdef INET6
114 else if (ip6) {
189#ifndef _KERNEL
190 struct sockaddr_in6 sin6;
191#endif
192
193 /* jumbo payload? */
194 fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
195 fp.fp_ttl = ip6->ip6_hlim;
196 fp.fp_flags |= PF_OSFP_DF;
197 fp.fp_flags |= PF_OSFP_INET6;
115 /* jumbo payload? */
116 fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
117 fp.fp_ttl = ip6->ip6_hlim;
118 fp.fp_flags |= PF_OSFP_DF;
119 fp.fp_flags |= PF_OSFP_INET6;
198#ifdef _KERNEL
199 strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
200 sizeof(srcname));
120 strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
121 sizeof(srcname));
201#else
202 memset(&sin6, 0, sizeof(sin6));
203 sin6.sin6_family = AF_INET6;
204 sin6.sin6_len = sizeof(struct sockaddr_in6);
205 sin6.sin6_addr = ip6->ip6_src;
206 (void)getnameinfo((struct sockaddr *)&sin6,
207 sizeof(struct sockaddr_in6), srcname, sizeof(srcname),
208 NULL, 0, NI_NUMERICHOST);
209#endif
210 }
211#endif
212 else
213 return (NULL);
214 fp.fp_wsize = ntohs(tcp->th_win);
215
216
217 cnt = (tcp->th_off << 2) - sizeof(*tcp);

--- 61 unchanged lines hidden (view full) ---

279 (fp.fp_flags & PF_OSFP_TS0) ? "0" : "",
280 (fp.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
281 (fp.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
282 fp.fp_mss,
283 (fp.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
284 (fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
285 fp.fp_wscale);
286
122 }
123#endif
124 else
125 return (NULL);
126 fp.fp_wsize = ntohs(tcp->th_win);
127
128
129 cnt = (tcp->th_off << 2) - sizeof(*tcp);

--- 61 unchanged lines hidden (view full) ---

191 (fp.fp_flags & PF_OSFP_TS0) ? "0" : "",
192 (fp.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
193 (fp.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
194 fp.fp_mss,
195 (fp.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
196 (fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
197 fp.fp_wscale);
198
287#ifdef __FreeBSD__
288 if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
199 if ((fpresult = pf_osfp_find(&V_pf_osfp_list, &fp,
289#else
290 if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
291#endif
292 PF_OSFP_MAXTTL_OFFSET)))
293 return (&fpresult->fp_oses);
294 return (NULL);
295}
296
297/* Match a fingerprint ID against a list of OSes */
298int
299pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)

--- 19 unchanged lines hidden (view full) ---

319 entry->fp_subtype_nm, os, entry->fp_os);
320 return (1);
321 }
322 }
323 DPFPRINTF("fingerprint 0x%x didn't match\n", os);
324 return (0);
325}
326
200 PF_OSFP_MAXTTL_OFFSET)))
201 return (&fpresult->fp_oses);
202 return (NULL);
203}
204
205/* Match a fingerprint ID against a list of OSes */
206int
207pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)

--- 19 unchanged lines hidden (view full) ---

227 entry->fp_subtype_nm, os, entry->fp_os);
228 return (1);
229 }
230 }
231 DPFPRINTF("fingerprint 0x%x didn't match\n", os);
232 return (0);
233}
234
327/* Initialize the OS fingerprint system */
328#ifdef __FreeBSD__
329int
330#else
331void
332#endif
333pf_osfp_initialize(void)
334{
335#if defined(__FreeBSD__) && defined(_KERNEL)
336 int error = ENOMEM;
337
338 do {
339 pf_osfp_entry_pl = pf_osfp_pl = NULL;
340 UMA_CREATE(pf_osfp_entry_pl, struct pf_osfp_entry, "pfospfen");
341 UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
342 error = 0;
343 } while(0);
344
345 SLIST_INIT(&V_pf_osfp_list);
346#else
347 pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
348 "pfosfpen", &pool_allocator_nointr);
349 pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
350 "pfosfp", &pool_allocator_nointr);
351 SLIST_INIT(&pf_osfp_list);
352#endif
353
354#ifdef __FreeBSD__
355#ifdef _KERNEL
356 return (error);
357#else
358 return (0);
359#endif
360#endif
361}
362
363#if defined(__FreeBSD__) && (_KERNEL)
364void
365pf_osfp_cleanup(void)
366{
367
368 UMA_DESTROY(pf_osfp_entry_pl);
369 UMA_DESTROY(pf_osfp_pl);
370}
371#endif
372
373/* Flush the fingerprint list */
374void
375pf_osfp_flush(void)
376{
377 struct pf_os_fingerprint *fp;
378 struct pf_osfp_entry *entry;
379
235/* Flush the fingerprint list */
236void
237pf_osfp_flush(void)
238{
239 struct pf_os_fingerprint *fp;
240 struct pf_osfp_entry *entry;
241
380#ifdef __FreeBSD__
381 while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
382 SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
242 while ((fp = SLIST_FIRST(&V_pf_osfp_list))) {
243 SLIST_REMOVE_HEAD(&V_pf_osfp_list, fp_next);
383#else
384 while ((fp = SLIST_FIRST(&pf_osfp_list))) {
385 SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
386#endif
387 while ((entry = SLIST_FIRST(&fp->fp_oses))) {
388 SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
244 while ((entry = SLIST_FIRST(&fp->fp_oses))) {
245 SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
389 pool_put(&pf_osfp_entry_pl, entry);
246 free(entry, M_PFOSFP);
390 }
247 }
391 pool_put(&pf_osfp_pl, fp);
248 free(fp, M_PFOSFP);
392 }
393}
394
395
396/* Add a fingerprint */
397int
398pf_osfp_add(struct pf_osfp_ioctl *fpioc)
399{
400 struct pf_os_fingerprint *fp, fpadd;
401 struct pf_osfp_entry *entry;
402
249 }
250}
251
252
253/* Add a fingerprint */
254int
255pf_osfp_add(struct pf_osfp_ioctl *fpioc)
256{
257 struct pf_os_fingerprint *fp, fpadd;
258 struct pf_osfp_entry *entry;
259
260 PF_RULES_WASSERT();
261
403 memset(&fpadd, 0, sizeof(fpadd));
404 fpadd.fp_tcpopts = fpioc->fp_tcpopts;
405 fpadd.fp_wsize = fpioc->fp_wsize;
406 fpadd.fp_psize = fpioc->fp_psize;
407 fpadd.fp_mss = fpioc->fp_mss;
408 fpadd.fp_flags = fpioc->fp_flags;
409 fpadd.fp_optcnt = fpioc->fp_optcnt;
410 fpadd.fp_wscale = fpioc->fp_wscale;

--- 20 unchanged lines hidden (view full) ---

431 (fpadd.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
432 fpadd.fp_mss,
433 (fpadd.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
434 (fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
435 fpadd.fp_wscale,
436 fpioc->fp_os.fp_os);
437#endif
438
262 memset(&fpadd, 0, sizeof(fpadd));
263 fpadd.fp_tcpopts = fpioc->fp_tcpopts;
264 fpadd.fp_wsize = fpioc->fp_wsize;
265 fpadd.fp_psize = fpioc->fp_psize;
266 fpadd.fp_mss = fpioc->fp_mss;
267 fpadd.fp_flags = fpioc->fp_flags;
268 fpadd.fp_optcnt = fpioc->fp_optcnt;
269 fpadd.fp_wscale = fpioc->fp_wscale;

--- 20 unchanged lines hidden (view full) ---

290 (fpadd.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
291 fpadd.fp_mss,
292 (fpadd.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
293 (fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
294 fpadd.fp_wscale,
295 fpioc->fp_os.fp_os);
296#endif
297
439#ifdef __FreeBSD__
440 if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
298 if ((fp = pf_osfp_find_exact(&V_pf_osfp_list, &fpadd))) {
441#else
442 if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
443#endif
444 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
445 if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
446 return (EEXIST);
447 }
299 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
300 if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
301 return (EEXIST);
302 }
448 if ((entry = pool_get(&pf_osfp_entry_pl,
449#ifdef __FreeBSD__
450 PR_NOWAIT)) == NULL)
451#else
452 PR_WAITOK|PR_LIMITFAIL)) == NULL)
453#endif
303 if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
304 == NULL)
454 return (ENOMEM);
455 } else {
305 return (ENOMEM);
306 } else {
456 if ((fp = pool_get(&pf_osfp_pl,
457#ifdef __FreeBSD__
458 PR_NOWAIT)) == NULL)
459#else
460 PR_WAITOK|PR_LIMITFAIL)) == NULL)
461#endif
307 if ((fp = malloc(sizeof(*fp), M_PFOSFP, M_ZERO | M_NOWAIT))
308 == NULL)
462 return (ENOMEM);
309 return (ENOMEM);
463 memset(fp, 0, sizeof(*fp));
464 fp->fp_tcpopts = fpioc->fp_tcpopts;
465 fp->fp_wsize = fpioc->fp_wsize;
466 fp->fp_psize = fpioc->fp_psize;
467 fp->fp_mss = fpioc->fp_mss;
468 fp->fp_flags = fpioc->fp_flags;
469 fp->fp_optcnt = fpioc->fp_optcnt;
470 fp->fp_wscale = fpioc->fp_wscale;
471 fp->fp_ttl = fpioc->fp_ttl;
472 SLIST_INIT(&fp->fp_oses);
310 fp->fp_tcpopts = fpioc->fp_tcpopts;
311 fp->fp_wsize = fpioc->fp_wsize;
312 fp->fp_psize = fpioc->fp_psize;
313 fp->fp_mss = fpioc->fp_mss;
314 fp->fp_flags = fpioc->fp_flags;
315 fp->fp_optcnt = fpioc->fp_optcnt;
316 fp->fp_wscale = fpioc->fp_wscale;
317 fp->fp_ttl = fpioc->fp_ttl;
318 SLIST_INIT(&fp->fp_oses);
473 if ((entry = pool_get(&pf_osfp_entry_pl,
474#ifdef __FreeBSD__
475 PR_NOWAIT)) == NULL) {
476#else
477 PR_WAITOK|PR_LIMITFAIL)) == NULL) {
478#endif
479 pool_put(&pf_osfp_pl, fp);
319 if ((entry = malloc(sizeof(*entry), M_PFOSFP, M_NOWAIT))
320 == NULL) {
321 free(fp, M_PFOSFP);
480 return (ENOMEM);
481 }
322 return (ENOMEM);
323 }
482#ifdef __FreeBSD__
483 pf_osfp_insert(&V_pf_osfp_list, fp);
324 pf_osfp_insert(&V_pf_osfp_list, fp);
484#else
485 pf_osfp_insert(&pf_osfp_list, fp);
486#endif
487 }
488 memcpy(entry, &fpioc->fp_os, sizeof(*entry));
489
490 /* Make sure the strings are NUL terminated */
491 entry->fp_class_nm[sizeof(entry->fp_class_nm)-1] = '\0';
492 entry->fp_version_nm[sizeof(entry->fp_version_nm)-1] = '\0';
493 entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
494
495 SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
496
497#ifdef PFDEBUG
498 if ((fp = pf_osfp_validate()))
499 printf("Invalid fingerprint list\n");
500#endif /* PFDEBUG */
501 return (0);
502}
503
504
505/* Find a fingerprint in the list */
325 }
326 memcpy(entry, &fpioc->fp_os, sizeof(*entry));
327
328 /* Make sure the strings are NUL terminated */
329 entry->fp_class_nm[sizeof(entry->fp_class_nm)-1] = '\0';
330 entry->fp_version_nm[sizeof(entry->fp_version_nm)-1] = '\0';
331 entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
332
333 SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
334
335#ifdef PFDEBUG
336 if ((fp = pf_osfp_validate()))
337 printf("Invalid fingerprint list\n");
338#endif /* PFDEBUG */
339 return (0);
340}
341
342
343/* Find a fingerprint in the list */
506struct pf_os_fingerprint *
344static struct pf_os_fingerprint *
507pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
508 u_int8_t ttldiff)
509{
510 struct pf_os_fingerprint *f;
511
512#define MATCH_INT(_MOD, _DC, _field) \
513 if ((f->fp_flags & _DC) == 0) { \
514 if ((f->fp_flags & _MOD) == 0) { \

--- 58 unchanged lines hidden (view full) ---

573 }
574 return (f);
575 }
576
577 return (NULL);
578}
579
580/* Find an exact fingerprint in the list */
345pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
346 u_int8_t ttldiff)
347{
348 struct pf_os_fingerprint *f;
349
350#define MATCH_INT(_MOD, _DC, _field) \
351 if ((f->fp_flags & _DC) == 0) { \
352 if ((f->fp_flags & _MOD) == 0) { \

--- 58 unchanged lines hidden (view full) ---

411 }
412 return (f);
413 }
414
415 return (NULL);
416}
417
418/* Find an exact fingerprint in the list */
581struct pf_os_fingerprint *
419static struct pf_os_fingerprint *
582pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
583{
584 struct pf_os_fingerprint *f;
585
586 SLIST_FOREACH(f, list, fp_next) {
587 if (f->fp_tcpopts == find->fp_tcpopts &&
588 f->fp_wsize == find->fp_wsize &&
589 f->fp_psize == find->fp_psize &&

--- 4 unchanged lines hidden (view full) ---

594 f->fp_ttl == find->fp_ttl)
595 return (f);
596 }
597
598 return (NULL);
599}
600
601/* Insert a fingerprint into the list */
420pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
421{
422 struct pf_os_fingerprint *f;
423
424 SLIST_FOREACH(f, list, fp_next) {
425 if (f->fp_tcpopts == find->fp_tcpopts &&
426 f->fp_wsize == find->fp_wsize &&
427 f->fp_psize == find->fp_psize &&

--- 4 unchanged lines hidden (view full) ---

432 f->fp_ttl == find->fp_ttl)
433 return (f);
434 }
435
436 return (NULL);
437}
438
439/* Insert a fingerprint into the list */
602void
440static void
603pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
604{
605 struct pf_os_fingerprint *f, *prev = NULL;
606
607 /* XXX need to go semi tree based. can key on tcp options */
608
609 SLIST_FOREACH(f, list, fp_next)
610 prev = f;

--- 9 unchanged lines hidden (view full) ---

620{
621 struct pf_os_fingerprint *fp;
622 struct pf_osfp_entry *entry;
623 int num = fpioc->fp_getnum;
624 int i = 0;
625
626
627 memset(fpioc, 0, sizeof(*fpioc));
441pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
442{
443 struct pf_os_fingerprint *f, *prev = NULL;
444
445 /* XXX need to go semi tree based. can key on tcp options */
446
447 SLIST_FOREACH(f, list, fp_next)
448 prev = f;

--- 9 unchanged lines hidden (view full) ---

458{
459 struct pf_os_fingerprint *fp;
460 struct pf_osfp_entry *entry;
461 int num = fpioc->fp_getnum;
462 int i = 0;
463
464
465 memset(fpioc, 0, sizeof(*fpioc));
628#ifdef __FreeBSD__
629 SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
466 SLIST_FOREACH(fp, &V_pf_osfp_list, fp_next) {
630#else
631 SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
632#endif
633 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
634 if (i++ == num) {
635 fpioc->fp_mss = fp->fp_mss;
636 fpioc->fp_wsize = fp->fp_wsize;
637 fpioc->fp_flags = fp->fp_flags;
638 fpioc->fp_psize = fp->fp_psize;
639 fpioc->fp_ttl = fp->fp_ttl;
640 fpioc->fp_wscale = fp->fp_wscale;

--- 4 unchanged lines hidden (view full) ---

645 }
646 }
647 }
648
649 return (EBUSY);
650}
651
652
467 SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
468 if (i++ == num) {
469 fpioc->fp_mss = fp->fp_mss;
470 fpioc->fp_wsize = fp->fp_wsize;
471 fpioc->fp_flags = fp->fp_flags;
472 fpioc->fp_psize = fp->fp_psize;
473 fpioc->fp_ttl = fp->fp_ttl;
474 fpioc->fp_wscale = fp->fp_wscale;

--- 4 unchanged lines hidden (view full) ---

479 }
480 }
481 }
482
483 return (EBUSY);
484}
485
486
487#ifdef PFDEBUG
653/* Validate that each signature is reachable */
488/* Validate that each signature is reachable */
654struct pf_os_fingerprint *
489static struct pf_os_fingerprint *
655pf_osfp_validate(void)
656{
657 struct pf_os_fingerprint *f, *f2, find;
658
490pf_osfp_validate(void)
491{
492 struct pf_os_fingerprint *f, *f2, find;
493
659#ifdef __FreeBSD__
660 SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
494 SLIST_FOREACH(f, &V_pf_osfp_list, fp_next) {
661#else
662 SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
663#endif
664 memcpy(&find, f, sizeof(find));
665
666 /* We do a few MSS/th_win percolations to make things unique */
667 if (find.fp_mss == 0)
668 find.fp_mss = 128;
669 if (f->fp_flags & PF_OSFP_WSIZE_MSS)
670 find.fp_wsize *= find.fp_mss;
671 else if (f->fp_flags & PF_OSFP_WSIZE_MTU)
672 find.fp_wsize *= (find.fp_mss + 40);
673 else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
674 find.fp_wsize *= 2;
495 memcpy(&find, f, sizeof(find));
496
497 /* We do a few MSS/th_win percolations to make things unique */
498 if (find.fp_mss == 0)
499 find.fp_mss = 128;
500 if (f->fp_flags & PF_OSFP_WSIZE_MSS)
501 find.fp_wsize *= find.fp_mss;
502 else if (f->fp_flags & PF_OSFP_WSIZE_MTU)
503 find.fp_wsize *= (find.fp_mss + 40);
504 else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
505 find.fp_wsize *= 2;
675#ifdef __FreeBSD__
676 if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
506 if (f != (f2 = pf_osfp_find(&V_pf_osfp_list, &find, 0))) {
677#else
678 if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
679#endif
680 if (f2)
681 printf("Found \"%s %s %s\" instead of "
682 "\"%s %s %s\"\n",
683 SLIST_FIRST(&f2->fp_oses)->fp_class_nm,
684 SLIST_FIRST(&f2->fp_oses)->fp_version_nm,
685 SLIST_FIRST(&f2->fp_oses)->fp_subtype_nm,
686 SLIST_FIRST(&f->fp_oses)->fp_class_nm,
687 SLIST_FIRST(&f->fp_oses)->fp_version_nm,
688 SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
689 else
690 printf("Couldn't find \"%s %s %s\"\n",
691 SLIST_FIRST(&f->fp_oses)->fp_class_nm,
692 SLIST_FIRST(&f->fp_oses)->fp_version_nm,
693 SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
694 return (f);
695 }
696 }
697 return (NULL);
698}
507 if (f2)
508 printf("Found \"%s %s %s\" instead of "
509 "\"%s %s %s\"\n",
510 SLIST_FIRST(&f2->fp_oses)->fp_class_nm,
511 SLIST_FIRST(&f2->fp_oses)->fp_version_nm,
512 SLIST_FIRST(&f2->fp_oses)->fp_subtype_nm,
513 SLIST_FIRST(&f->fp_oses)->fp_class_nm,
514 SLIST_FIRST(&f->fp_oses)->fp_version_nm,
515 SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
516 else
517 printf("Couldn't find \"%s %s %s\"\n",
518 SLIST_FIRST(&f->fp_oses)->fp_class_nm,
519 SLIST_FIRST(&f->fp_oses)->fp_version_nm,
520 SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
521 return (f);
522 }
523 }
524 return (NULL);
525}
526#endif /* PFDEBUG */