summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2006-12-13 05:10:16 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2006-12-13 05:10:16 +0000
commita47cbe32d5a8bf07aca6d6d9c94c040d1658f15b (patch)
tree863c4ee84dfd5bb638d4f81029e1042157ffe841
parent676cabb26db08770818f948b13e3965cf7e3e3f7 (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.c10
-rw-r--r--sys/net/pf_osfp.c90
-rw-r--r--sys/net/pfvar.h7
-rw-r--r--usr.sbin/tcpdump/pfctl_osfp.c10
-rw-r--r--usr.sbin/tcpdump/print-tcp.c35
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:");