dect
/
libpcap
Archived
13
0
Fork 0

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:
guy 2005-04-19 04:26:06 +00:00
parent 6e0b3eb7a1
commit 73ce1b460d
7 changed files with 369 additions and 9 deletions

View File

@ -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
View File

@ -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 */

View File

@ -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. */

View File

@ -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; }

View File

@ -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)
{

View File

@ -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 *);

View File

@ -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