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.
This commit is contained in:
parent
6e0b3eb7a1
commit
73ce1b460d
1
CREDITS
1
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>
|
||||
|
|
316
gencode.c
316
gencode.c
|
@ -21,7 +21,7 @@
|
|||
*/
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.4 2005-04-18 22:40:14 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.5 2005-04-19 04:26:06 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 */
|
||||
|
|
|
@ -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.60.2.1 2005-04-19 04:26:07 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. */
|
||||
|
||||
|
|
|
@ -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.86.2.1 2005-04-19 04:26:08 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; }
|
||||
|
|
47
nametoaddr.c
47
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.77.2.1 2005-04-19 04:26:08 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)
|
||||
{
|
||||
|
|
|
@ -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.10.2.1 2005-04-19 04:26:08 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 *);
|
||||
|
|
|
@ -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.99.2.1 2005-04-19 04:26:08 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
|
||||
|
|
Reference in New Issue