diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2006-12-13 05:10:16 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2006-12-13 05:10:16 +0000 |
commit | a47cbe32d5a8bf07aca6d6d9c94c040d1658f15b (patch) | |
tree | 863c4ee84dfd5bb638d4f81029e1042157ffe841 | |
parent | 676cabb26db08770818f948b13e3965cf7e3e3f7 (diff) |
IPv6 passive OS fingerprinting.
reuses IPv4 signature file (assuming that TCP code is shared among IPv4/v6).
mcbride ok.
-rw-r--r-- | sbin/pfctl/pfctl_osfp.c | 10 | ||||
-rw-r--r-- | sys/net/pf_osfp.c | 90 | ||||
-rw-r--r-- | sys/net/pfvar.h | 7 | ||||
-rw-r--r-- | usr.sbin/tcpdump/pfctl_osfp.c | 10 | ||||
-rw-r--r-- | usr.sbin/tcpdump/print-tcp.c | 35 |
5 files changed, 117 insertions, 35 deletions
diff --git a/sbin/pfctl/pfctl_osfp.c b/sbin/pfctl/pfctl_osfp.c index 0fe5a1426e5..7018d6cd365 100644 --- a/sbin/pfctl/pfctl_osfp.c +++ b/sbin/pfctl/pfctl_osfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_osfp.c,v 1.14 2006/04/08 02:13:14 ray Exp $ */ +/* $OpenBSD: pfctl_osfp.c,v 1.15 2006/12/13 05:10:15 itojun Exp $ */ /* * Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org> @@ -23,6 +23,10 @@ #include <net/if.h> #include <net/pfvar.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> + #include <ctype.h> #include <err.h> #include <errno.h> @@ -240,6 +244,10 @@ pfctl_file_fingerprints(int dev, int opts, const char *fp_filename) sizeof(fp.fp_os.fp_subtype_nm)); add_fingerprint(dev, opts, &fp); + + fp.fp_flags |= (PF_OSFP_DF | PF_OSFP_INET6); + fp.fp_psize += sizeof(struct ip6_hdr) - sizeof(struct ip); + add_fingerprint(dev, opts, &fp); } if (class) diff --git a/sys/net/pf_osfp.c b/sys/net/pf_osfp.c index b2adcf29667..1f55e136b02 100644 --- a/sys/net/pf_osfp.c +++ b/sys/net/pf_osfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf_osfp.c,v 1.10 2004/04/09 19:30:41 frantzen Exp $ */ +/* $OpenBSD: pf_osfp.c,v 1.11 2006/12/13 05:10:15 itojun Exp $ */ /* * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.org> @@ -32,9 +32,10 @@ #include <net/if.h> #include <net/pfvar.h> -#ifdef INET6 #include <netinet/ip6.h> -#endif /* INET6 */ +#ifdef _KERNEL +#include <netinet6/in6_var.h> +#endif #ifdef _KERNEL @@ -51,6 +52,7 @@ typedef struct pool pool_t; # include <stdio.h> # include <stdlib.h> # include <string.h> +# include <netdb.h> # define pool_t int # define pool_get(pool, flags) malloc(*(pool)) # define pool_put(pool, item) free(item) @@ -87,38 +89,92 @@ pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off, const struct tcphdr *tcp) { struct ip *ip; + struct ip6_hdr *ip6; char hdr[60]; - /* XXX don't have a fingerprint database for IPv6 :-( */ - if (pd->af != PF_INET || pd->proto != IPPROTO_TCP || (tcp->th_off << 2) - < sizeof(*tcp)) + if ((pd->af != PF_INET && pd->af != PF_INET6) || + pd->proto != IPPROTO_TCP || (tcp->th_off << 2) < sizeof(*tcp)) return (NULL); - ip = mtod(m, struct ip *); - if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL, pd->af)) - return (NULL); + if (pd->af == PF_INET) { + ip = mtod(m, struct ip *); + ip6 = (struct ip6_hdr *)NULL; + } else { + ip = (struct ip *)NULL; + ip6 = mtod(m, struct ip6_hdr *); + } + if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL, + pd->af)) return (NULL); - return (pf_osfp_fingerprint_hdr(ip, (struct tcphdr *)hdr)); + return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr)); } #endif /* _KERNEL */ struct pf_osfp_enlist * -pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp) +pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp) { struct pf_os_fingerprint fp, *fpresult; int cnt, optlen = 0; const u_int8_t *optp; +#ifdef _KERNEL + char srcname[128]; +#else + char srcname[NI_MAXHOST]; +#endif - if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN || (ip->ip_off & - htons(IP_OFFMASK))) + if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN) return (NULL); + if (ip) { + if ((ip->ip_off & htons(IP_OFFMASK)) != 0) + return (NULL); + } memset(&fp, 0, sizeof(fp)); - fp.fp_psize = ntohs(ip->ip_len); - fp.fp_ttl = ip->ip_ttl; - if (ip->ip_off & htons(IP_DF)) + if (ip) { +#ifndef _KERNEL + struct sockaddr_in sin; +#endif + + fp.fp_psize = ntohs(ip->ip_len); + fp.fp_ttl = ip->ip_ttl; + if (ip->ip_off & htons(IP_DF)) + fp.fp_flags |= PF_OSFP_DF; +#ifdef _KERNEL + strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname)); +#else + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(struct sockaddr_in); + sin.sin_addr = ip->ip_src; + (void)getnameinfo((struct sockaddr *)&sin, + sizeof(struct sockaddr_in), srcname, sizeof(srcname), + NULL, 0, NI_NUMERICHOST); +#endif + } else if (ip6) { +#ifndef _KERNEL + struct sockaddr_in6 sin6; +#endif + + /* jumbo payload? */ + fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); + fp.fp_ttl = ip6->ip6_hlim; fp.fp_flags |= PF_OSFP_DF; + fp.fp_flags |= PF_OSFP_INET6; +#ifdef _KERNEL + strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src), + sizeof(srcname)); +#else + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_addr = ip6->ip6_src; + (void)getnameinfo((struct sockaddr *)&sin6, + sizeof(struct sockaddr_in6), srcname, sizeof(srcname), + NULL, 0, NI_NUMERICHOST); +#endif + } else + return (NULL); fp.fp_wsize = ntohs(tcp->th_win); @@ -181,7 +237,7 @@ pf_osfp_fingerprint_hdr(const struct ip *ip, const struct tcphdr *tcp) DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) " "(TS=%s,M=%s%d,W=%s%d)\n", - inet_ntoa(ip->ip_src), ntohs(tcp->th_sport), + srcname, ntohs(tcp->th_sport), fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0, fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt, (fp.fp_flags & PF_OSFP_TS0) ? "0" : "", diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 3ca96a61b30..b5f11fb9a0c 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.241 2006/11/20 14:25:11 mcbride Exp $ */ +/* $OpenBSD: pfvar.h,v 1.242 2006/12/13 05:10:15 itojun Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -45,6 +45,7 @@ #include <netinet/tcp_fsm.h> struct ip; +struct ip6_hdr; #define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0) #define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1) @@ -452,6 +453,7 @@ struct pf_os_fingerprint { #define PF_OSFP_MSS_DC 0x0800 /* TCP MSS dont-care */ #define PF_OSFP_DF 0x1000 /* IPv4 don't fragment bit */ #define PF_OSFP_TS0 0x2000 /* Zero timestamp */ +#define PF_OSFP_INET6 0x4000 /* IPv6 */ u_int8_t fp_optcnt; /* TCP option count */ u_int8_t fp_wscale; /* TCP window scaling */ u_int8_t fp_ttl; /* IPv4 TTL */ @@ -1643,7 +1645,8 @@ struct pf_osfp_enlist * const struct tcphdr *); #endif /* _KERNEL */ struct pf_osfp_enlist * - pf_osfp_fingerprint_hdr(const struct ip *, const struct tcphdr *); + pf_osfp_fingerprint_hdr(const struct ip *, const struct ip6_hdr *, + const struct tcphdr *); void pf_osfp_flush(void); int pf_osfp_get(struct pf_osfp_ioctl *); void pf_osfp_initialize(void); diff --git a/usr.sbin/tcpdump/pfctl_osfp.c b/usr.sbin/tcpdump/pfctl_osfp.c index 90a728dc58a..55c665032bc 100644 --- a/usr.sbin/tcpdump/pfctl_osfp.c +++ b/usr.sbin/tcpdump/pfctl_osfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfctl_osfp.c,v 1.3 2005/02/17 13:18:00 aaron Exp $ */ +/* $OpenBSD: pfctl_osfp.c,v 1.4 2006/12/13 05:10:15 itojun Exp $ */ /* * Copyright (c) 2003 Mike Frantzen <frantzen@openbsd.org> @@ -30,6 +30,10 @@ #include <stdlib.h> #include <string.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> + #include "privsep.h" #include "pfctl_parser.h" @@ -241,6 +245,10 @@ pfctl_file_fingerprints(int dev, int opts, const char *fp_filename) sizeof(fp.fp_os.fp_subtype_nm)); add_fingerprint(dev, opts, &fp); + + fp.fp_os.fp_enflags |= (PF_OSFP_DF | PF_OSFP_INET6); + fp.fp_psize += sizeof(struct ip6_hdr) - sizeof(struct ip); + add_fingerprint(dev, opts, &fp); } if (class) diff --git a/usr.sbin/tcpdump/print-tcp.c b/usr.sbin/tcpdump/print-tcp.c index 16e6e61e844..0d0426cc395 100644 --- a/usr.sbin/tcpdump/print-tcp.c +++ b/usr.sbin/tcpdump/print-tcp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: print-tcp.c,v 1.24 2006/05/28 22:48:16 moritz Exp $ */ +/* $OpenBSD: print-tcp.c,v 1.25 2006/12/13 05:10:15 itojun Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -23,7 +23,7 @@ #ifndef lint static const char rcsid[] = - "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-tcp.c,v 1.24 2006/05/28 22:48:16 moritz Exp $ (LBL)"; + "@(#) $Header: /cvs/OpenBSD/src/usr.sbin/tcpdump/print-tcp.c,v 1.25 2006/12/13 05:10:15 itojun Exp $ (LBL)"; #endif #include <sys/param.h> @@ -195,13 +195,24 @@ tcp_print(register const u_char *bp, register u_int length, #endif tp = (struct tcphdr *)bp; - ip = (struct ip *)bp2; + switch (((struct ip *)bp2)->ip_v) { + case 4: + ip = (struct ip *)bp2; #ifdef INET6 - if (ip->ip_v == 6) - ip6 = (struct ip6_hdr *)bp2; - else ip6 = NULL; -#endif /*INET6*/ +#endif + break; +#ifdef INET6 + case 6: + ip = NULL; + ip6 = (struct ip6_hdr *)bp2; + break; +#endif + default: + (void)printf("invalid ip version"); + return; + } + ch = '\0'; if (length < sizeof(*tp)) { (void)printf("truncated-tcp %d", length); @@ -400,7 +411,7 @@ tcp_print(register const u_char *bp, register u_int length, return; } - if (ip->ip_v == 4 && vflag) { + if (ip && ip->ip_v == 4 && vflag) { int sum; if (TTEST2(tp->th_sport, length)) { sum = tcp_cksum(ip, tp, length); @@ -412,18 +423,14 @@ tcp_print(register const u_char *bp, register u_int length, } /* OS Fingerprint */ - if (oflag && -#ifdef INET6 - ip6 == NULL && -#endif - (flags & (TH_SYN|TH_ACK)) == TH_SYN) { + if (oflag && (flags & (TH_SYN|TH_ACK)) == TH_SYN) { struct pf_osfp_enlist *head = NULL; struct pf_osfp_entry *fp; unsigned long left; left = (unsigned long)(snapend - (const u_char *)tp); if (left >= hlen) - head = pf_osfp_fingerprint_hdr(ip, tp); + head = pf_osfp_fingerprint_hdr(ip, ip6, tp); if (head) { int prev = 0; printf(" (src OS:"); |