summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorguy <guy>2005-04-19 04:25:00 +0000
committerguy <guy>2005-04-19 04:25:00 +0000
commit97a8e5112d9f004bec63db30c42e16a96e0aab0b (patch)
tree41dfe802a98622ba4db42735acbaa06b37310a3a
parentb423e170246706185004faa75aab6cbe68000280 (diff)
downloadlibpcap-97a8e5112d9f004bec63db30c42e16a96e0aab0b.tar.gz
From Patrick Marie <mycroft@virgaria.org>: add support for port ranges
in tests - "portrange X-Y" matches all ports in the range [X,Y]. Support added for port ranges with IPv6. Fix some comments.
-rw-r--r--CREDITS1
-rw-r--r--gencode.c316
-rw-r--r--gencode.h3
-rw-r--r--grammar.y5
-rw-r--r--nametoaddr.c47
-rw-r--r--pcap-namedb.h3
-rw-r--r--scanner.l3
7 files changed, 369 insertions, 9 deletions
diff --git a/CREDITS b/CREDITS
index 1cc579b8..7c0e9cc0 100644
--- a/CREDITS
+++ b/CREDITS
@@ -68,6 +68,7 @@ Additional people who have contributed patches:
Octavian Cerna <tavy@ylabs.com>
Olaf Kirch <okir@caldera.de>
Onno van der Linden <onno@simplex.nl>
+ Patrick Marie <mycroft@virgaria.org>
Paul Mundt <lethal@linux-sh.org>
Pavel Kankovsky <kan@dcit.cz>
Peter Fales <peter@fales-lorenz.net>
diff --git a/gencode.c b/gencode.c
index a2540e06..79ff45f0 100644
--- a/gencode.c
+++ b/gencode.c
@@ -21,7 +21,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.230 2005-04-18 22:36:45 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.231 2005-04-19 04:25:00 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -193,14 +193,20 @@ static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
#endif
static struct block *gen_ipfrag(void);
static struct block *gen_portatom(int, bpf_int32);
+static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
#ifdef INET6
static struct block *gen_portatom6(int, bpf_int32);
+static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
#endif
struct block *gen_portop(int, int, int);
static struct block *gen_port(int, int, int);
+struct block *gen_portrangeop(int, int, int, int);
+static struct block *gen_portrange(int, int, int, int);
#ifdef INET6
struct block *gen_portop6(int, int, int);
static struct block *gen_port6(int, int, int);
+struct block *gen_portrangeop6(int, int, int, int);
+static struct block *gen_portrange6(int, int, int, int);
#endif
static int lookup_proto(const char *, int);
static struct block *gen_protochain(int, int, int);
@@ -3315,7 +3321,7 @@ gen_portop6(port, proto, dir)
{
struct block *b0, *b1, *tmp;
- /* ip proto 'proto' */
+ /* ip6 proto 'proto' */
b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
switch (dir) {
@@ -3356,7 +3362,7 @@ gen_port6(port, ip_proto, dir)
{
struct block *b0, *b1, *tmp;
- /* ether proto ip */
+ /* link proto ip6 */
b0 = gen_linktype(ETHERTYPE_IPV6);
switch (ip_proto) {
@@ -3382,6 +3388,242 @@ gen_port6(port, ip_proto, dir)
}
#endif /* INET6 */
+/* gen_portrange code */
+struct block *
+gen_portrangeatom(off, v1, v2)
+ int off;
+ bpf_int32 v1, v2;
+{
+ struct slist *s1, *s2;
+ struct block *b1, *b2;
+
+ if (v1 > v2) {
+ /*
+ * Reverse the order of the ports, so v1 is the lower one.
+ */
+ bpf_int32 vtemp;
+
+ vtemp = v1;
+ v1 = v2;
+ v2 = vtemp;
+ }
+ s1 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s1->s.k = off_nl;
+
+ s1->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
+ s1->next->s.k = off_nl + off;
+
+ b1 = new_block(JMP(BPF_JGE));
+ b1->stmts = s1;
+ b1->s.k = v1;
+
+ s2 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s2->s.k = off_nl;
+
+ s2->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
+ s2->next->s.k = off_nl + off;
+
+ b2 = new_block(JMP(BPF_JGT));
+ gen_not(b2);
+ b2->stmts = s2;
+ b2->s.k = v2;
+
+ gen_and(b1, b2);
+
+ return b2;
+}
+
+struct block *
+gen_portrangeop(port1, port2, proto, dir)
+ int port1, port2;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip proto 'proto' */
+ tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto);
+ b0 = gen_ipfrag();
+ gen_and(tmp, b0);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_DST:
+ b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_OR:
+ case Q_DEFAULT:
+ tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_AND:
+ tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_and(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_portrange(port1, port2, ip_proto, dir)
+ int port1, port2;
+ int ip_proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* link proto ip */
+ b0 = gen_linktype(ETHERTYPE_IP);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portrangeop(port1, port2, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+#ifdef INET6
+struct block *
+gen_portrangeatom6(off, v1, v2)
+ int off;
+ bpf_int32 v1, v2;
+{
+ struct slist *s1, *s2;
+ struct block *b1, *b2;
+
+ if (v1 > v2) {
+ /*
+ * Reverse the order of the ports, so v1 is the lower one.
+ */
+ bpf_int32 vtemp;
+
+ vtemp = v1;
+ v1 = v2;
+ v2 = vtemp;
+ }
+
+ s1 = new_stmt(BPF_LD|BPF_ABS|BPF_H);
+ s1->s.k = off_nl + 40 + off;
+
+ b1 = new_block(JMP(BPF_JGE));
+ b1->stmts = s1;
+ b1->s.k = v1;
+
+ s2 = new_stmt(BPF_LD|BPF_ABS|BPF_H);
+ s2->s.k = off_nl + 40 + off;
+
+ b2 = new_block(JMP(BPF_JGT));
+ gen_not(b2);
+ b2->stmts = s2;
+ b2->s.k = v2;
+
+ gen_and(b1, b2);
+
+ return b2;
+}
+
+struct block *
+gen_portrangeop6(port1, port2, proto, dir)
+ int port1, port2;
+ int proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip6 proto 'proto' */
+ b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_DST:
+ b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_OR:
+ case Q_DEFAULT:
+ tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_AND:
+ tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_and(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_portrange6(port1, port2, ip_proto, dir)
+ int port1, port2;
+ int ip_proto;
+ int dir;
+{
+ struct block *b0, *b1, *tmp;
+
+ /* link proto ip6 */
+ b0 = gen_linktype(ETHERTYPE_IPV6);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+#endif /* INET6 */
+
static int
lookup_proto(name, proto)
register const char *name;
@@ -3963,6 +4205,7 @@ gen_scode(name, q)
#endif /*INET6*/
struct block *b, *tmp;
int port, real_proto;
+ int port1, port2;
switch (q.addr) {
@@ -4170,6 +4413,50 @@ gen_scode(name, q)
}
#endif /* INET6 */
+ case Q_PORTRANGE:
+ if (proto != Q_DEFAULT &&
+ proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
+ bpf_error("illegal qualifier of 'portrange'");
+ if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
+ bpf_error("unknown port in range '%s'", name);
+ if (proto == Q_UDP) {
+ if (real_proto == IPPROTO_TCP)
+ bpf_error("port in range '%s' is tcp", name);
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error("port in range '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_UDP;
+ }
+ if (proto == Q_TCP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error("port in range '%s' is udp", name);
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error("port in range '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_TCP;
+ }
+ if (proto == Q_SCTP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error("port in range '%s' is udp", name);
+ else if (real_proto == IPPROTO_TCP)
+ bpf_error("port in range '%s' is tcp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_SCTP;
+ }
+#ifndef INET6
+ return gen_portrange(port1, port2, real_proto, dir);
+#else
+ {
+ struct block *b;
+ b = gen_portrange(port1, port2, real_proto, dir);
+ gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
+ return b;
+ }
+#endif /* INET6 */
+
case Q_GATEWAY:
#ifndef INET6
eaddr = pcap_ether_hostton(name);
@@ -4317,6 +4604,29 @@ gen_ncode(s, v, q)
}
#endif /* INET6 */
+ case Q_PORTRANGE:
+ if (proto == Q_UDP)
+ proto = IPPROTO_UDP;
+ else if (proto == Q_TCP)
+ proto = IPPROTO_TCP;
+ else if (proto == Q_SCTP)
+ proto = IPPROTO_SCTP;
+ else if (proto == Q_DEFAULT)
+ proto = PROTO_UNDEF;
+ else
+ bpf_error("illegal qualifier of 'portrange'");
+
+#ifndef INET6
+ return gen_portrange((int)v, (int)v, proto, dir);
+#else
+ {
+ struct block *b;
+ b = gen_portrange((int)v, (int)v, proto, dir);
+ gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
+ return b;
+ }
+#endif /* INET6 */
+
case Q_GATEWAY:
bpf_error("'gateway' requires a name");
/* NOTREACHED */
diff --git a/gencode.h b/gencode.h
index 6b97e892..f6e0523a 100644
--- a/gencode.h
+++ b/gencode.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60 2004-06-16 08:20:30 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.61 2005-04-19 04:25:00 guy Exp $ (LBL)
*/
/*
@@ -63,6 +63,7 @@
#define Q_GATEWAY 4
#define Q_PROTO 5
#define Q_PROTOCHAIN 6
+#define Q_PORTRANGE 7
/* Protocol qualifiers. */
diff --git a/grammar.y b/grammar.y
index 3325b764..1a86044f 100644
--- a/grammar.y
+++ b/grammar.y
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86 2004-12-18 08:49:23 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.87 2005-04-19 04:25:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -114,7 +114,7 @@ pcap_parse()
%type <blk> atmfieldvalue atmvalue atmlistvalue
%token DST SRC HOST GATEWAY
-%token NET NETMASK PORT LESS GREATER PROTO PROTOCHAIN CBYTE
+%token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE
%token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP
%token ATALK AARP DECNET LAT SCA MOPRC MOPDL
%token TK_BROADCAST TK_MULTICAST
@@ -271,6 +271,7 @@ dqual: SRC { $$ = Q_SRC; }
aqual: HOST { $$ = Q_HOST; }
| NET { $$ = Q_NET; }
| PORT { $$ = Q_PORT; }
+ | PORTRANGE { $$ = Q_PORTRANGE; }
;
/* non-directional address type qualifiers */
ndaqual: GATEWAY { $$ = Q_GATEWAY; }
diff --git a/nametoaddr.c b/nametoaddr.c
index 8f033b44..c6e74a0a 100644
--- a/nametoaddr.c
+++ b/nametoaddr.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77 2005-03-27 22:26:25 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.78 2005-04-19 04:25:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -216,6 +216,51 @@ pcap_nametoport(const char *name, int *port, int *proto)
return 0;
}
+/*
+ * Convert a string in the form PPP-PPP, where correspond to ports, to
+ * a starting and ending port in a port range.
+ * Return 0 on failure.
+ */
+int
+pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
+{
+ u_int p1, p2;
+ char *off, *cpy;
+ int save_proto;
+
+ if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
+ if ((cpy = strdup(name)) == NULL)
+ return 0;
+
+ if ((off = strchr(cpy, '-')) == NULL) {
+ free(cpy);
+ return 0;
+ }
+
+ *off = '\0';
+
+ if (pcap_nametoport(cpy, port1, proto) == 0) {
+ free(cpy);
+ return 0;
+ }
+ save_proto = *proto;
+
+ if (pcap_nametoport(off + 1, port2, proto) == 0) {
+ free(cpy);
+ return 0;
+ }
+
+ if (*proto != save_proto)
+ *proto = PROTO_UNDEF;
+ } else {
+ *port1 = p1;
+ *port2 = p2;
+ *proto = PROTO_UNDEF;
+ }
+
+ return 1;
+}
+
int
pcap_nametoproto(const char *str)
{
diff --git a/pcap-namedb.h b/pcap-namedb.h
index ba02ee0f..2d1bd277 100644
--- a/pcap-namedb.h
+++ b/pcap-namedb.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10 2005-03-17 07:02:32 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.11 2005-04-19 04:25:01 guy Exp $ (LBL)
*/
#ifndef lib_pcap_namedb_h
@@ -65,6 +65,7 @@ struct addrinfo *pcap_nametoaddrinfo(const char *);
bpf_u_int32 pcap_nametonetaddr(const char *);
int pcap_nametoport(const char *, int *, int *);
+int pcap_nametoportrange(const char *, int *, int *, int *);
int pcap_nametoproto(const char *);
int pcap_nametoeproto(const char *);
int pcap_nametollc(const char *);
diff --git a/scanner.l b/scanner.l
index f03d04e7..0c6fad50 100644
--- a/scanner.l
+++ b/scanner.l
@@ -22,7 +22,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99 2004-06-16 08:20:28 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.100 2005-04-19 04:25:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -234,6 +234,7 @@ host return HOST;
net return NET;
mask return NETMASK;
port return PORT;
+portrange return PORTRANGE;
proto return PROTO;
protochain {
#ifdef NO_PROTOCHAIN