diff options
Diffstat (limited to 'contrib/ipfilter/tools')
| -rw-r--r-- | contrib/ipfilter/tools/BNF.ipf | 2 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/Makefile | 17 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipf.c | 149 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipf_y.y | 1288 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipfcomp.c | 140 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipfs.c | 46 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipfstat.c | 1073 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipfsyncd.c | 671 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipftest.c | 414 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipmon.c | 1252 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipmon_y.y | 722 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipnat.c | 542 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipnat_y.y | 1560 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ippool.c | 436 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ippool_y.y | 551 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipscan_y.y | 5 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipsyncm.c | 46 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/ipsyncs.c | 52 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/lex_var.h | 2 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/lexer.c | 128 | ||||
| -rw-r--r-- | contrib/ipfilter/tools/lexer.h | 8 |
21 files changed, 6473 insertions, 2631 deletions
diff --git a/contrib/ipfilter/tools/BNF.ipf b/contrib/ipfilter/tools/BNF.ipf index 0e8433291d1c..0740c5855af9 100644 --- a/contrib/ipfilter/tools/BNF.ipf +++ b/contrib/ipfilter/tools/BNF.ipf @@ -66,7 +66,7 @@ facility = "kern" | "user" | "mail" | "daemon" | "auth" | "syslog" | "audit" | "logalert" | "local0" | "local1" | "local2" | "local3" | "local4" | "local5" | "local6" | "local7" . priority = "emerg" | "alert" | "crit" | "err" | "warn" | "notice" | - "info" | "debug" . + "info" | "debug" . hexnumber = "0" "x" hexstring . hexstring = hexdigit [ hexstring ] . diff --git a/contrib/ipfilter/tools/Makefile b/contrib/ipfilter/tools/Makefile index 43ec1a897b83..ce1ab0e6fc22 100644 --- a/contrib/ipfilter/tools/Makefile +++ b/contrib/ipfilter/tools/Makefile @@ -1,8 +1,5 @@ -# -# Copyright (C) 1993-2001 by Darren Reed. -# -# See the IPFILTER.LICENCE file for details on licencing. -# +YACC=yacc -v + DEST=. all: $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c \ @@ -16,7 +13,7 @@ all: $(DEST)/ipf_y.c $(DEST)/ipf_y.h $(DEST)/ipf_l.c \ $(DEST)/ipf_y.h: $(DEST)/ipf_y.c $(DEST)/ipf_y.c: ipf_y.y - yacc -d ipf_y.y + $(YACC) -d ipf_y.y sed -e 's/yy/ipf_yy/g' -e 's/y.tab.h/ipf_y.c/' \ -e 's/"ipf_y.y"/"..\/tools\/ipf_y.y"/' \ y.tab.c > $(DEST)/ipf_y.c @@ -30,7 +27,7 @@ $(DEST)/ipf_l.c: lexer.c $(DEST)/ipmon_y.n: $(DEST)/ipmon_y.c $(DEST)/ipmon_y.c $(DEST)/ipmon_y.h: ipmon_y.y - yacc -d ipmon_y.y + $(YACC) -d ipmon_y.y sed -e 's/yy/ipmon_yy/g' -e 's/"ipmon_y.y"/"..\/tools\/ipmon_y.y"/' \ y.tab.c > $(DEST)/ipmon_y.c sed -e 's/yy/ipmon_yy/g' y.tab.h > $(DEST)/ipmon_y.h @@ -43,7 +40,7 @@ $(DEST)/ipmon_l.c: lexer.c $(DEST)/ipscan_y.h: $(DEST)/ipscan_y.c $(DEST)/ipscan_y.c $(DEST)/ipscan_y.h: ipscan_y.y - yacc -d ipscan_y.y + $(YACC) -d ipscan_y.y sed -e 's/yy/ipscan_yy/g' \ -e 's/"ipscan_y.y"/"..\/tools\/ipscan_y.y"/' \ y.tab.c > $(DEST)/ipscan_y.c @@ -57,7 +54,7 @@ $(DEST)/ipscan_l.c: lexer.c $(DEST)/ippool_y.h: $(DEST)/ippool_y.c $(DEST)/ippool_y.c $(DEST)/ippool_y.h: ippool_y.y - yacc -d ippool_y.y + $(YACC) -d ippool_y.y sed -e 's/yy/ippool_yy/g' -e 's/"ippool_y.y"/"..\/tools\/ippool_y.y"/' \ y.tab.c > $(DEST)/ippool_y.c sed -e 's/yy/ippool_yy/g' y.tab.h > $(DEST)/ippool_y.h @@ -70,7 +67,7 @@ $(DEST)/ippool_l.c: lexer.c $(DEST)/ipnat_y.h: $(DEST)/ipnat_y.c $(DEST)/ipnat_y.c $(DEST)/ipnat_y.h: ipnat_y.y - yacc -d ipnat_y.y + $(YACC) -d ipnat_y.y sed -e 's/yy/ipnat_yy/g' -e 's/y.tab.c/ipnat_y.c/' \ -e s/\"ipnat_y.y\"/\"..\\/tools\\/ipnat_y.y\"/ \ y.tab.c > $(DEST)/ipnat_y.c diff --git a/contrib/ipfilter/tools/ipf.c b/contrib/ipfilter/tools/ipf.c index fe9fec2581ec..dd601426debd 100644 --- a/contrib/ipfilter/tools/ipf.c +++ b/contrib/ipfilter/tools/ipf.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -16,12 +16,13 @@ #endif #include "ipf.h" #include <fcntl.h> +#include <ctype.h> #include <sys/ioctl.h> #include "netinet/ipl.h" #if !defined(lint) static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipf.c,v 1.35.2.8 2007/05/10 06:12:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #if !defined(__SVR4) && defined(__GNUC__) @@ -40,23 +41,30 @@ int main __P((int, char *[])); int opts = 0; int outputc = 0; int use_inet6 = 0; +int exitstatus = 0; -static void procfile __P((char *, char *)), flushfilter __P((char *)); -static void set_state __P((u_int)), showstats __P((friostat_t *)); -static void packetlogon __P((char *)), swapactive __P((void)); +static void procfile __P((char *)); +static void flushfilter __P((char *, int *)); +static void set_state __P((u_int)); +static void showstats __P((friostat_t *)); +static void packetlogon __P((char *)); +static void swapactive __P((void)); static int opendevice __P((char *, int)); static void closedevice __P((void)); static char *ipfname = IPL_NAME; static void usage __P((void)); static int showversion __P((void)); static int get_flags __P((void)); -static void ipf_interceptadd __P((int, ioctlfunc_t, void *)); +static int ipf_interceptadd __P((int, ioctlfunc_t, void *)); static int fd = -1; static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ioctl, ioctl, ioctl, ioctl, ioctl, ioctl, ioctl, ioctl }; +/* XXX The following was added to satisfy a rescue/rescue/ build + XXX requirement. */ +int nohdrfields; static void usage() { @@ -68,25 +76,28 @@ static void usage() int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - int c; + int c, *filter = NULL; if (argc < 2) usage(); - while ((c = getopt(argc, argv, "6Ac:dDEf:F:Il:noPrRsT:vVyzZ")) != -1) { + assigndefined(getenv("IPF_PREDEFINED")); + + while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) { switch (c) { case '?' : usage(); break; -#ifdef USE_INET6 + case '4' : + use_inet6 = -1; + break; case '6' : use_inet6 = 1; break; -#endif case 'A' : opts &= ~OPT_INACTIVE; break; @@ -104,10 +115,10 @@ char *argv[]; opts ^= OPT_DEBUG; break; case 'f' : - procfile(argv[0], optarg); + procfile(optarg); break; case 'F' : - flushfilter(optarg); + flushfilter(optarg, filter); break; case 'I' : opts ^= OPT_INACTIVE; @@ -115,8 +126,11 @@ char *argv[]; case 'l' : packetlogon(optarg); break; + case 'm' : + filter = parseipfexpr(optarg, NULL); + break; case 'n' : - opts ^= OPT_DONOTHING; + opts ^= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : break; @@ -161,14 +175,14 @@ char *argv[]; if (fd != -1) (void) close(fd); - return(0); + return(exitstatus); /* NOTREACHED */ } static int opendevice(ipfdev, check) -char *ipfdev; -int check; + char *ipfdev; + int check; { if (opts & OPT_DONOTHING) return -2; @@ -184,7 +198,7 @@ int check; if (fd == -1) if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) - perror("open device"); + ipferror(fd, "open device"); return fd; } @@ -202,7 +216,7 @@ static int get_flags() if ((opendevice(ipfname, 1) != -2) && (ioctl(fd, SIOCGETFF, &i) == -1)) { - perror("SIOCGETFF"); + ipferror(fd, "SIOCGETFF"); return 0; } return i; @@ -210,22 +224,24 @@ static int get_flags() static void set_state(enable) -u_int enable; + u_int enable; { - if (opendevice(ipfname, 0) != -2) + if (opendevice(ipfname, 0) != -2) { if (ioctl(fd, SIOCFRENB, &enable) == -1) { - if (errno == EBUSY) + if (errno == EBUSY) { fprintf(stderr, "IP FIlter: already initialized\n"); - else - perror("SIOCFRENB"); + } else { + ipferror(fd, "SIOCFRENB"); + } } + } return; } -static void procfile(name, file) -char *name, *file; +static void procfile(file) + char *file; { (void) opendevice(ipfname, 1); @@ -241,20 +257,22 @@ char *name, *file; } -static void ipf_interceptadd(fd, ioctlfunc, ptr) -int fd; -ioctlfunc_t ioctlfunc; -void *ptr; +static int ipf_interceptadd(fd, ioctlfunc, ptr) + int fd; + ioctlfunc_t ioctlfunc; + void *ptr; { if (outputc) printc(ptr); - ipf_addrule(fd, ioctlfunc, ptr); + if (ipf_addrule(fd, ioctlfunc, ptr) != 0) + exitstatus = 1; + return 0; } static void packetlogon(opt) -char *opt; + char *opt; { int flag, xfd, logopt, change = 0; @@ -293,7 +311,7 @@ char *opt; if (change == 1) { if (opendevice(ipfname, 1) != -2 && (ioctl(fd, SIOCSETFF, &flag) != 0)) - perror("ioctl(SIOCSETFF)"); + ipferror(fd, "ioctl(SIOCSETFF)"); } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { @@ -308,11 +326,11 @@ char *opt; if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) - perror("ioctl(SIOCGETLG)"); + ipferror(fd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) - perror("ioctl(SIOCSETLG)"); + ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } @@ -325,11 +343,11 @@ char *opt; if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) - perror("ioctl(SIOCGETLG)"); + ipferror(xfd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) - perror("ioctl(SIOCSETLG)"); + ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } @@ -337,8 +355,9 @@ char *opt; } -static void flushfilter(arg) -char *arg; +static void flushfilter(arg, filter) + char *arg; + int *filter; { int fl = 0, rem; @@ -359,20 +378,33 @@ char *arg; if (!(opts & OPT_DONOTHING)) { if (use_inet6) { - if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); - exit(1); + fprintf(stderr, + "IPv6 rules are no longer seperate\n"); + } else if (filter != NULL) { + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = filter[0] * sizeof(int); + obj.ipfo_type = IPFOBJ_IPFEXPR; + obj.ipfo_ptr = filter; + if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { + ipferror(fd, "ioctl(SIOCMATCHFLUSH)"); + fl = -1; + } else { + fl = obj.ipfo_retval; } } else { if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); + ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s (%d)\n", arg, rem); - printf("removed %d entries\n", fl); + } + if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + printf("%d state entries removed\n", fl); } closedevice(); return; @@ -388,7 +420,7 @@ char *arg; perror("open(IPL_AUTH)"); else { if (ioctl(fd, SIOCIPFFA, &fl) == -1) - perror("ioctl(SIOCIPFFA)"); + ipferror(fd, "ioctl(SIOCIPFFA)"); } closedevice(); return; @@ -411,21 +443,23 @@ char *arg; if (!(opts & OPT_DONOTHING)) { if (use_inet6) { if (ioctl(fd, SIOCIPFL6, &fl) == -1) { - perror("ioctl(SIOCIPFL6)"); + ipferror(fd, "ioctl(SIOCIPFL6)"); exit(1); } } else { if (ioctl(fd, SIOCIPFFL, &fl) == -1) { - perror("ioctl(SIOCIPFFL)"); + ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } - if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "", (rem & FR_OUTQUE) ? "O" : "", rem); - printf("removed %d filter rules\n", fl); + } + if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { + printf("%d filter rules removed\n", fl); } return; } @@ -436,7 +470,7 @@ static void swapactive() int in = 2; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) - perror("ioctl(SIOCSWAPA)"); + ipferror(fd, "ioctl(SIOCSWAPA)"); else printf("Set %d now inactive\n", in); } @@ -447,7 +481,7 @@ void ipf_frsync() int frsyn = 0; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1) - perror("SIOCFRSYN"); + ipferror(fd, "SIOCFRSYN"); else printf("filter sync'd\n"); } @@ -466,7 +500,7 @@ void zerostats() if (opendevice(ipfname, 1) != -2) { if (ioctl(fd, SIOCFRZST, &obj) == -1) { - perror("ioctl(SIOCFRZST)"); + ipferror(fd, "ioctl(SIOCFRZST)"); exit(-1); } showstats(&fio); @@ -479,7 +513,7 @@ void zerostats() * read the kernel stats for packets blocked and passed */ static void showstats(fp) -friostat_t *fp; + friostat_t *fp; { printf("bad packets:\t\tin %lu\tout %lu\n", fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); @@ -495,9 +529,6 @@ friostat_t *fp; fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); printf("output packets logged:\tblocked %lu passed %lu\n", fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - printf(" packets logged:\tinput %lu-%lu output %lu-%lu\n", - fp->f_st[0].fr_pkl, fp->f_st[0].fr_skip, - fp->f_st[1].fr_pkl, fp->f_st[1].fr_skip); } @@ -523,7 +554,7 @@ static int showversion() } if (ioctl(vfd, SIOCGETFS, &ipfo)) { - perror("ioctl(SIOCGETFS)"); + ipferror(vfd, "ioctl(SIOCGETFS)"); close(vfd); return 1; } diff --git a/contrib/ipfilter/tools/ipf_y.y b/contrib/ipfilter/tools/ipf_y.y index 82307dec0328..822e9a5ab0ca 100644 --- a/contrib/ipfilter/tools/ipf_y.y +++ b/contrib/ipfilter/tools/ipf_y.y @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -28,18 +28,29 @@ extern int yydebug; extern FILE *yyin; extern int yylineNum; -static void newrule __P((void)); -static void setipftype __P((void)); -static u_32_t lookuphost __P((char *)); +static int addname __P((frentry_t **, char *)); +static frentry_t *addrule __P((void)); +static frentry_t *allocfr __P((void)); +static void build_dstaddr_af __P((frentry_t *, void *)); +static void build_srcaddr_af __P((frentry_t *, void *)); static void dobpf __P((int, char *)); -static void resetaddr __P((void)); -static struct alist_s *newalist __P((struct alist_s *)); +static void doipfexpr __P((char *)); +static void do_tuneint __P((char *, int)); +static void do_tunestr __P((char *, char *)); +static void fillgroup __P((frentry_t *)); +static int lookuphost __P((char *, i6addr_t *)); static u_int makehash __P((struct alist_s *)); static int makepool __P((struct alist_s *)); -static frentry_t *addrule __P((void)); +static struct alist_s *newalist __P((struct alist_s *)); +static void newrule __P((void)); +static void resetaddr __P((void)); +static void setgroup __P((frentry_t **, char *)); +static void setgrhead __P((frentry_t **, char *)); +static void seticmphead __P((frentry_t **, char *)); +static void setifname __P((frentry_t **, int, char *)); +static void setipftype __P((void)); static void setsyslog __P((void)); static void unsetsyslog __P((void)); -static void fillgroup __P((frentry_t *)); frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL; @@ -52,52 +63,54 @@ static int nrules = 0; static int newlist = 0; static int added = 0; static int ipffd = -1; -static int *yycont = 0; -static ioctlfunc_t ipfioctl[IPL_LOGSIZE]; +static int *yycont = NULL; +static ioctlfunc_t ipfioctls[IPL_LOGSIZE]; static addfunc_t ipfaddfunc = NULL; -static struct wordtab ipfwords[95]; -static struct wordtab addrwords[4]; -static struct wordtab maskwords[5]; -static struct wordtab icmpcodewords[17]; -static struct wordtab icmptypewords[16]; -static struct wordtab ipv4optwords[25]; -static struct wordtab ipv4secwords[9]; -static struct wordtab ipv6optwords[9]; -static struct wordtab logwords[33]; %} %union { char *str; u_32_t num; - struct in_addr ipa; frentry_t fr; frtuc_t *frt; struct alist_s *alist; u_short port; + struct in_addr ip4; struct { u_short p1; u_short p2; int pc; } pc; - struct { + struct ipp_s { + int type; + int ifpos; + int f; + int v; + int lif; union i6addr a; union i6addr m; + char *name; } ipp; - union i6addr ip6; + struct { + i6addr_t adr; + int f; + } adr; + i6addr_t ip6; struct { char *if1; char *if2; } ifs; + char gname[FR_GROUPLEN]; }; %type <port> portnum %type <num> facility priority icmpcode seclevel secname icmptype %type <num> opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr -%type <num> portc porteq -%type <ipa> hostname ipv4 ipv4mask ipv4_16 ipv4_24 -%type <ip6> ipv6mask +%type <num> portc porteq ipmask maskopts +%type <ip4> ipv4 ipv4_16 ipv4_24 +%type <adr> hostname %type <ipp> addr ipaddr -%type <str> servicename name interfacename +%type <str> servicename name interfacename groupname %type <pc> portrange portcomp %type <alist> addrlist poollist %type <ifs> onname @@ -109,30 +122,32 @@ static struct wordtab logwords[33]; %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 +%token IPFY_SET %token IPFY_PASS IPFY_BLOCK IPFY_COUNT IPFY_CALL IPFY_NOMATCH %token IPFY_RETICMP IPFY_RETRST IPFY_RETICMPASDST %token IPFY_IN IPFY_OUT %token IPFY_QUICK IPFY_ON IPFY_OUTVIA IPFY_INVIA %token IPFY_DUPTO IPFY_TO IPFY_FROUTE IPFY_REPLY_TO IPFY_ROUTETO -%token IPFY_TOS IPFY_TTL IPFY_PROTO +%token IPFY_TOS IPFY_TTL IPFY_PROTO IPFY_INET IPFY_INET6 %token IPFY_HEAD IPFY_GROUP %token IPFY_AUTH IPFY_PREAUTH -%token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK -%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP +%token IPFY_LOG IPFY_BODY IPFY_FIRST IPFY_LEVEL IPFY_ORBLOCK IPFY_L5AS +%token IPFY_LOGTAG IPFY_MATCHTAG IPFY_SETTAG IPFY_SKIP IPFY_DECAPS %token IPFY_FROM IPFY_ALL IPFY_ANY IPFY_BPFV4 IPFY_BPFV6 IPFY_POOL IPFY_HASH -%token IPFY_PPS +%token IPFY_IPFEXPR IPFY_PPS IPFY_FAMILY IPFY_DSTLIST %token IPFY_ESP IPFY_AH %token IPFY_WITH IPFY_AND IPFY_NOT IPFY_NO IPFY_OPT %token IPFY_TCPUDP IPFY_TCP IPFY_UDP %token IPFY_FLAGS IPFY_MULTICAST %token IPFY_MASK IPFY_BROADCAST IPFY_NETWORK IPFY_NETMASKED IPFY_PEER -%token IPFY_PORT -%token IPFY_NOW +%token IPFY_RPC IPFY_PORT +%token IPFY_NOW IPFY_COMMENT IPFY_RULETTL %token IPFY_ICMP IPFY_ICMPTYPE IPFY_ICMPCODE %token IPFY_IPOPTS IPFY_SHORT IPFY_NAT IPFY_BADSRC IPFY_LOWTTL IPFY_FRAG %token IPFY_MBCAST IPFY_BAD IPFY_BADNAT IPFY_OOW IPFY_NEWISN IPFY_NOICMPERR %token IPFY_KEEP IPFY_STATE IPFY_FRAGS IPFY_LIMIT IPFY_STRICT IPFY_AGE -%token IPFY_SYNC IPFY_FRAGBODY +%token IPFY_SYNC IPFY_FRAGBODY IPFY_ICMPHEAD IPFY_NOLOG IPFY_LOOSE +%token IPFY_MAX_SRCS IPFY_MAX_PER_SRC %token IPFY_IPOPT_NOP IPFY_IPOPT_RR IPFY_IPOPT_ZSU IPFY_IPOPT_MTUP %token IPFY_IPOPT_MTUR IPFY_IPOPT_ENCODE IPFY_IPOPT_TS IPFY_IPOPT_TR %token IPFY_IPOPT_SEC IPFY_IPOPT_LSRR IPFY_IPOPT_ESEC IPFY_IPOPT_CIPSO @@ -140,10 +155,10 @@ static struct wordtab logwords[33]; %token IPFY_IPOPT_IMITD IPFY_IPOPT_EIP IPFY_IPOPT_FINN IPFY_IPOPT_DPS %token IPFY_IPOPT_SDB IPFY_IPOPT_NSAPA IPFY_IPOPT_RTRALRT IPFY_IPOPT_UMP %token IPFY_SECCLASS IPFY_SEC_UNC IPFY_SEC_CONF IPFY_SEC_RSV1 IPFY_SEC_RSV2 -%token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 +%token IPFY_SEC_RSV4 IPFY_SEC_SEC IPFY_SEC_TS IPFY_SEC_RSV3 IPFY_DOI -%token IPF6_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS -%token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING +%token IPFY_V6HDRS IPFY_IPV6OPT IPFY_IPV6OPT_DSTOPTS IPFY_IPV6OPT_HOPOPTS +%token IPFY_IPV6OPT_IPV6 IPFY_IPV6OPT_NONE IPFY_IPV6OPT_ROUTING IPFY_V6HDR %token IPFY_IPV6OPT_MOBILITY IPFY_IPV6OPT_ESP IPFY_IPV6OPT_FRAG %token IPFY_ICMPT_UNR IPFY_ICMPT_ECHO IPFY_ICMPT_ECHOR IPFY_ICMPT_SQUENCH @@ -168,16 +183,36 @@ static struct wordtab logwords[33]; %token IPFY_PRI_EMERG IPFY_PRI_ALERT IPFY_PRI_CRIT IPFY_PRI_ERR IPFY_PRI_WARN %token IPFY_PRI_NOTICE IPFY_PRI_INFO IPFY_PRI_DEBUG %% -file: line +file: settings rules + | rules + ; + +settings: + YY_COMMENT + | setting + | settings setting + ; + +rules: line | assign - | file line - | file assign + | rules line + | rules assign + ; + +setting: + IPFY_SET YY_STR YY_NUMBER ';' { do_tuneint($2, $3); } + | IPFY_SET YY_STR YY_HEX ';' { do_tuneint($2, $3); } + | IPFY_SET YY_STR YY_STR ';' { do_tunestr($2, $3); } ; line: rule { while ((fr = frtop) != NULL) { frtop = fr->fr_next; fr->fr_next = NULL; - (*ipfaddfunc)(ipffd, ipfioctl[IPL_LOGIPF], fr); + if ((fr->fr_type == FR_T_IPF) && + (fr->fr_ip.fi_v == 0)) + fr->fr_mip.fi_v = 0; + /* XXX validate ? */ + (*ipfaddfunc)(ipffd, ipfioctls[IPL_LOGIPF], fr); fr->fr_next = frold; frold = fr; } @@ -231,10 +266,37 @@ markout: rulemain: ipfrule | bpfrule + | exprrule ; ipfrule: - tos ttl proto ip + family tos ttl proto ip + ; + +family: | IPFY_FAMILY IPFY_INET { if (use_inet6 == 1) { + YYERROR; + } else { + frc->fr_family = AF_INET; + } + } + | IPFY_INET { if (use_inet6 == 1) { + YYERROR; + } else { + frc->fr_family = AF_INET; + } + } + | IPFY_FAMILY IPFY_INET6 { if (use_inet6 == -1) { + YYERROR; + } else { + frc->fr_family = AF_INET6; + } + } + | IPFY_INET6 { if (use_inet6 == -1) { + YYERROR; + } else { + frc->fr_family = AF_INET6; + } + } ; bpfrule: @@ -242,12 +304,16 @@ bpfrule: | IPFY_BPFV6 '{' YY_STR '}' { dobpf(6, $3); free($3); } ; +exprrule: + IPFY_IPFEXPR '{' YY_STR '}' { doipfexpr($3); } + ; + ruletail: with keep head group ; ruletail2: - pps age new + pps age new rulettl comment ; intag: settagin matchtagin @@ -269,6 +335,7 @@ action: block | IPFY_NOMATCH { fr->fr_flags |= FR_NOMATCH; } | log | IPFY_COUNT { fr->fr_flags |= FR_ACCOUNT; } + | decaps { fr->fr_flags |= FR_DECAPSULATE; } | auth | IPFY_SKIP YY_NUMBER { fr->fr_flags |= FR_SKIP; fr->fr_arg = $2; } @@ -291,6 +358,11 @@ blockreturn: | IPFY_RETRST { fr->fr_flags |= FR_RETRST; } ; +decaps: IPFY_DECAPS + | IPFY_DECAPS IPFY_L5AS '(' YY_STR ')' + { fr->fr_icode = atoi($4); } + ; + log: IPFY_LOG { fr->fr_flags |= FR_LOG; } | IPFY_LOG logoptions { fr->fr_flags |= FR_LOG; } ; @@ -300,10 +372,11 @@ auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; } | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; } ; -func: YY_STR '/' YY_NUMBER { fr->fr_func = nametokva($1, - ipfioctl[IPL_LOGIPF]); - fr->fr_arg = $3; - free($1); } +func: YY_STR '/' YY_NUMBER + { fr->fr_func = nametokva($1, ipfioctls[IPL_LOGIPF]); + fr->fr_arg = $3; + free($1); + } ; inopts: @@ -330,6 +403,7 @@ outopt: | on | dup | proute + | froute | replyto ; @@ -346,7 +420,7 @@ toslist: | YY_HEX { DOREM(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } | toslist lmore YY_NUMBER { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } - | toslist lmore YY_HEX + | toslist lmore YY_HEX { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } ; @@ -355,10 +429,10 @@ ttl: | setttl YY_NUMBER | setttl lstart ttllist lend ; -lstart: '(' { newlist = 1; fr = frc; added = 0; } +lstart: '{' { newlist = 1; fr = frc; added = 0; } ; -lend: ')' { nrules += added; } +lend: '}' { nrules += added; } ; lmore: lanother { if (newlist == 1) { @@ -394,20 +468,25 @@ protox: IPFY_PROTO { setipftype(); ip: srcdst flags icmp ; -group: | IPFY_GROUP YY_STR { DOALL(strncpy(fr->fr_group, $2, \ - FR_GROUPLEN); \ - fillgroup(fr);); - free($2); } - | IPFY_GROUP YY_NUMBER { DOALL(sprintf(fr->fr_group, "%d", \ - $2); \ - fillgroup(fr);) } +group: | IPFY_GROUP groupname { DOALL(setgroup(&fr, $2); \ + fillgroup(fr);); + free($2); + } + ; + +head: | IPFY_HEAD groupname { DOALL(setgrhead(&fr, $2);); + free($2); + } ; -head: | IPFY_HEAD YY_STR { DOALL(strncpy(fr->fr_grhead, $2, \ - FR_GROUPLEN);); - free($2); } - | IPFY_HEAD YY_NUMBER { DOALL(sprintf(fr->fr_grhead, "%d", \ - $2);) } +groupname: + YY_STR { $$ = $1; + if (strlen($$) >= FR_GROUPLEN) + $$[FR_GROUPLEN - 1] = '\0'; + } + | YY_NUMBER { $$ = malloc(16); + sprintf($$, "%d", $1); + } ; settagin: @@ -461,6 +540,15 @@ pps: | IPFY_PPS YY_NUMBER { DOALL(fr->fr_pps = $2;) } new: | savegroup file restoregroup ; +rulettl: + | IPFY_RULETTL YY_NUMBER { DOALL(fr->fr_die = $2;) } + ; + +comment: + | IPFY_COMMENT YY_STR { DOALL(fr->fr_comment = addname(&fr, \ + $2);) } + ; + savegroup: '{' ; @@ -472,76 +560,92 @@ restoregroup: logopt: log ; -quick: - IPFY_QUICK { fr->fr_flags |= FR_QUICK; } +quick: IPFY_QUICK { fr->fr_flags |= FR_QUICK; } ; -on: IPFY_ON onname +on: IPFY_ON onname { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } | IPFY_ON lstart onlist lend - | IPFY_ON onname IPFY_INVIA vianame - | IPFY_ON onname IPFY_OUTVIA vianame + | IPFY_ON onname IPFY_INVIA vianame { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } + | IPFY_ON onname IPFY_OUTVIA vianame { setifname(&fr, 0, $2.if1); + free($2.if1); + if ($2.if2 != NULL) { + setifname(&fr, 1, + $2.if2); + free($2.if2); + } + } ; -onlist: onname { DOREM(strncpy(fr->fr_ifnames[0], $1.if1, \ - sizeof(fr->fr_ifnames[0])); \ - if ($1.if2 != NULL) { \ - strncpy(fr->fr_ifnames[1], \ - $1.if2, \ - sizeof(fr->fr_ifnames[1]));\ - } \ - ) } - | onlist lmore onname { DOREM(strncpy(fr->fr_ifnames[0], $3.if1, \ - sizeof(fr->fr_ifnames[0])); \ - if ($3.if2 != NULL) { \ - strncpy(fr->fr_ifnames[1], \ - $3.if2, \ - sizeof(fr->fr_ifnames[1]));\ - } \ - ) } +onlist: onname { DOREM(setifname(&fr, 0, $1.if1); \ + if ($1.if2 != NULL) \ + setifname(&fr, 1, $1.if2); \ + ) + free($1.if1); + if ($1.if2 != NULL) + free($1.if2); + } + | onlist lmore onname { DOREM(setifname(&fr, 0, $3.if1); \ + if ($3.if2 != NULL) \ + setifname(&fr, 1, $3.if2); \ + ) + free($3.if1); + if ($3.if2 != NULL) + free($3.if2); + } ; -onname: interfacename - { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); - $$.if1 = fr->fr_ifnames[0]; - $$.if2 = NULL; - free($1); - } +onname: interfacename { $$.if1 = $1; + $$.if2 = NULL; + } | interfacename ',' interfacename - { strncpy(fr->fr_ifnames[0], $1, sizeof(fr->fr_ifnames[0])); - $$.if1 = fr->fr_ifnames[0]; - free($1); - strncpy(fr->fr_ifnames[1], $3, sizeof(fr->fr_ifnames[1])); - $$.if1 = fr->fr_ifnames[1]; - free($3); - } + { $$.if1 = $1; + $$.if2 = $3; + } ; vianame: - name - { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); - free($1); - } - | name ',' name - { strncpy(fr->fr_ifnames[2], $1, sizeof(fr->fr_ifnames[2])); - free($1); - strncpy(fr->fr_ifnames[3], $3, sizeof(fr->fr_ifnames[3])); - free($3); - } + name { setifname(&fr, 2, $1); + free($1); + } + | name ',' name { setifname(&fr, 2, $1); + free($1); + setifname(&fr, 3, $3); + free($3); + } ; dup: IPFY_DUPTO name - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_dif.fd_name = idx; free($2); } - | IPFY_DUPTO name duptoseparator hostname - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); - fr->fr_dif.fd_ip = $4; - yyexpectaddr = 0; - free($2); + | IPFY_DUPTO IPFY_DSTLIST '/' name + { int idx = addname(&fr, $4); + fr->fr_dif.fd_name = idx; + fr->fr_dif.fd_type = FRD_DSTLIST; + free($4); } - | IPFY_DUPTO name duptoseparator YY_IPV6 - { strncpy(fr->fr_dif.fd_ifname, $2, sizeof(fr->fr_dif.fd_ifname)); - bcopy(&$4, &fr->fr_dif.fd_ip6, sizeof(fr->fr_dif.fd_ip6)); + | IPFY_DUPTO name duptoseparator hostname + { int idx = addname(&fr, $2); + fr->fr_dif.fd_name = idx; + fr->fr_dif.fd_ptr = (void *)-1; + fr->fr_dif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; yyexpectaddr = 0; free($2); } @@ -555,18 +659,23 @@ froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } ; proute: routeto name - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_tif.fd_name = idx; free($2); } - | routeto name duptoseparator hostname - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); - fr->fr_tif.fd_ip = $4; - yyexpectaddr = 0; - free($2); + | routeto IPFY_DSTLIST '/' name + { int idx = addname(&fr, $4); + fr->fr_tif.fd_name = idx; + fr->fr_tif.fd_type = FRD_DSTLIST; + free($4); } - | routeto name duptoseparator YY_IPV6 - { strncpy(fr->fr_tif.fd_ifname, $2, sizeof(fr->fr_tif.fd_ifname)); - bcopy(&$4, &fr->fr_tif.fd_ip6, sizeof(fr->fr_tif.fd_ip6)); + | routeto name duptoseparator hostname + { int idx = addname(&fr, $2); + fr->fr_tif.fd_name = idx; + fr->fr_tif.fd_ptr = (void *)-1; + fr->fr_tif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; yyexpectaddr = 0; free($2); } @@ -579,12 +688,22 @@ routeto: replyto: IPFY_REPLY_TO name - { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); + { int idx = addname(&fr, $2); + fr->fr_rif.fd_name = idx; free($2); } + | IPFY_REPLY_TO IPFY_DSTLIST '/' name + { fr->fr_rif.fd_name = addname(&fr, $4); + fr->fr_rif.fd_type = FRD_DSTLIST; + free($4); + } | IPFY_REPLY_TO name duptoseparator hostname - { strncpy(fr->fr_rif.fd_ifname, $2, sizeof(fr->fr_rif.fd_ifname)); - fr->fr_rif.fd_ip = $4; + { int idx = addname(&fr, $2); + fr->fr_rif.fd_name = idx; + fr->fr_rif.fd_ptr = (void *)-1; + fr->fr_rif.fd_ip6 = $4.adr; + if (fr->fr_family == AF_UNSPEC && $4.f != AF_UNSPEC) + fr->fr_family = $4.f; free($2); } ; @@ -614,27 +733,29 @@ srcdst: | IPFY_ALL ; protocol: - YY_NUMBER { DOREM(fr->fr_proto = $1; \ - fr->fr_mproto = 0xff;) } + YY_NUMBER { DOALL(fr->fr_proto = $1; \ + fr->fr_mproto = 0xff;) + } | YY_STR { if (!strcmp($1, "tcp-udp")) { - DOREM(fr->fr_flx |= FI_TCPUDP; \ + DOALL(fr->fr_flx |= FI_TCPUDP; \ fr->fr_mflx |= FI_TCPUDP;) } else { int p = getproto($1); if (p == -1) yyerror("protocol unknown"); - DOREM(fr->fr_proto = p; \ + DOALL(fr->fr_proto = p; \ fr->fr_mproto = 0xff;) } free($1); - } + } | YY_STR nextstring YY_STR { if (!strcmp($1, "tcp") && !strcmp($3, "udp")) { DOREM(fr->fr_flx |= FI_TCPUDP; \ fr->fr_mflx |= FI_TCPUDP;) - } else + } else { YYERROR; + } free($1); free($3); } @@ -667,7 +788,8 @@ to: IPFY_TO { if (fr == NULL) printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); - resetaddr(); } + resetaddr(); + } ; with: | andwith withlist @@ -678,7 +800,7 @@ andwith: | IPFY_AND { nowith = 0; setipftype(); } ; -flags: | startflags flagset +flags: | startflags flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } | startflags flagset '/' flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } @@ -717,35 +839,14 @@ srcobject: ; srcaddr: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + addr { build_srcaddr_af(fr, &$1); } | lstart srcaddrlist lend ; srcaddrlist: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_src, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_src, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + addr { build_srcaddr_af(fr, &$1); } | srcaddrlist lmore addr - { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_src, sizeof($3.a)); \ - bcopy(&($3.m), &fr->fr_mip.fi_src, sizeof($3.m)); \ - if (dynamic != -1) { \ - fr->fr_satype = ifpflag; \ - fr->fr_ipf->fri_sifpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_satype = FRI_LOOKUP;) - } + { build_srcaddr_af(fr, &$3); } ; srcport: @@ -770,10 +871,10 @@ fromport: srcportlist: portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) } - | portnum ':' portnum + | portnum ':' portnum { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } - | portnum YY_RANGE_IN portnum + | portnum YY_RANGE_IN portnum { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } | srcportlist lmore portnum @@ -794,34 +895,25 @@ dstobject: ; dstaddr: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($1.f != frc->fr_family)) + yyerror("1.src/dst address family mismatch"); + build_dstaddr_af(fr, &$1); } | lstart dstaddrlist lend ; dstaddrlist: - addr { DOREM(bcopy(&($1.a), &fr->fr_ip.fi_dst, sizeof($1.a)); \ - bcopy(&($1.m), &fr->fr_mip.fi_dst, sizeof($1.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + addr { if (($1.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($1.f != frc->fr_family)) + yyerror("2.src/dst address family mismatch"); + build_dstaddr_af(fr, &$1); } | dstaddrlist lmore addr - { DOREM(bcopy(&($3.a), &fr->fr_ip.fi_dst, sizeof($3.a)); \ - bcopy(&($3.m), &fr->fr_mip.fi_dst, sizeof($3.m)); \ - if (dynamic != -1) { \ - fr->fr_datype = ifpflag; \ - fr->fr_ipf->fri_difpidx = dynamic; \ - } else if (pooled || hashed) \ - fr->fr_datype = FRI_LOOKUP;) + { if (($3.f != AF_UNSPEC) && (frc->fr_family != AF_UNSPEC) && + ($3.f != frc->fr_family)) + yyerror("3.src/dst address family mismatch"); + build_dstaddr_af(fr, &$3); } ; @@ -848,10 +940,10 @@ toport: dstportlist: portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) } - | portnum ':' portnum + | portnum ':' portnum { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } - | portnum YY_RANGE_IN portnum + | portnum YY_RANGE_IN portnum { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } | dstportlist lmore portnum @@ -865,141 +957,234 @@ dstportlist: ; addr: pool '/' YY_NUMBER { pooled = 1; + yyexpectaddr = 0; + $$.type = FRI_LOOKUP; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 0; $$.a.iplookupnum = $3; } | pool '/' YY_STR { pooled = 1; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 1; - strncpy($$.a.iplookupname, $3, - sizeof($$.a.iplookupname)); + $$.a.iplookupname = addname(&fr, $3); + } + | pool '=' '(' { yyexpectaddr = 1; + pooled = 1; } - | pool '=' '(' poollist ')' { pooled = 1; + poollist ')' { yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_POOL; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = makepool($4); } + $$.a.iplookupnum = makepool($5); + } | hash '/' YY_NUMBER { hashed = 1; + yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = $3; } - | hash '/' YY_STR { pooled = 1; + $$.a.iplookupnum = $3; + } + | hash '/' YY_STR { hashed = 1; + $$.type = FRI_LOOKUP; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 1; - strncpy($$.a.iplookupname, $3, - sizeof($$.a.iplookupname)); + $$.a.iplookupname = addname(&fr, $3); } - | hash '=' '(' addrlist ')' { hashed = 1; + | hash '=' '(' { hashed = 1; + yyexpectaddr = 1; + } + addrlist ')' { yyexpectaddr = 0; + $$.v = 0; + $$.ifpos = -1; + $$.f = AF_UNSPEC; + $$.type = FRI_LOOKUP; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 0; - $$.a.iplookupnum = makehash($4); } - | ipaddr { bcopy(&$1, &$$, sizeof($$)); + $$.a.iplookupnum = makehash($5); + } + | ipaddr { $$ = $1; yyexpectaddr = 0; } ; ipaddr: IPFY_ANY { bzero(&($$), sizeof($$)); + $$.type = FRI_NORMAL; + $$.ifpos = -1; + yyexpectaddr = 0; + } + | hostname { $$.a = $1.adr; + $$.f = $1.f; + if ($1.f == AF_INET6) + fill6bits(128, $$.m.i6); + else if ($1.f == AF_INET) + fill6bits(32, $$.m.i6); + $$.v = ftov($1.f); + $$.ifpos = dynamic; + $$.type = FRI_NORMAL; + } + | hostname { yyresetdict(); } + maskspace { yysetdict(maskwords); + yyexpectaddr = 2; } + ipmask { ntomask($1.f, $5, $$.m.i6); + $$.a = $1.adr; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + $$.type = ifpflag; + $$.ifpos = dynamic; + if (ifpflag != 0 && $$.v == 0) { + if (frc->fr_family == AF_INET6){ + $$.v = 6; + $$.f = AF_INET6; + } else { + $$.v = 4; + $$.f = AF_INET; + } + } yyresetdict(); - yyexpectaddr = 0; } - | hostname { $$.a.in4 = $1; - $$.m.in4_addr = 0xffffffff; - yyexpectaddr = 0; } - | hostname { yyresetdict(); - $$.a.in4_addr = $1.s_addr; } - maskspace { yysetdict(maskwords); } - ipv4mask { $$.m.in4_addr = $5.s_addr; - $$.a.in4_addr &= $5.s_addr; - yyresetdict(); - yyexpectaddr = 0; } - | YY_IPV6 { bcopy(&$1, &$$.a, sizeof($$.a)); - fill6bits(128, (u_32_t *)&$$.m); + yyexpectaddr = 0; + } + | '(' YY_STR ')' { $$.type = FRI_DYNAMIC; + ifpflag = FRI_DYNAMIC; + $$.ifpos = addname(&fr, $2); + $$.lif = 0; + } + | '(' YY_STR ')' '/' + { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } + maskopts + { $$.type = ifpflag; + $$.ifpos = addname(&fr, $2); + $$.lif = 0; + if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (ifpflag == FRI_DYNAMIC) { + ntomask(frc->fr_family, + $6, $$.m.i6); + } yyresetdict(); - yyexpectaddr = 0; } - | YY_IPV6 { yyresetdict(); - bcopy(&$1, &$$.a, sizeof($$.a)); } - maskspace { yysetdict(maskwords); } - ipv6mask { bcopy(&$5, &$$.m, sizeof($$.m)); + yyexpectaddr = 0; + } + | '(' YY_STR ':' YY_NUMBER ')' '/' + { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } + maskopts + { $$.type = ifpflag; + $$.ifpos = addname(&fr, $2); + $$.lif = $4; + if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (ifpflag == FRI_DYNAMIC) { + ntomask(frc->fr_family, + $8, $$.m.i6); + } yyresetdict(); - yyexpectaddr = 0; } + yyexpectaddr = 0; + } ; + maskspace: '/' | IPFY_MASK ; -ipv4mask: - ipv4 { $$ = $1; } - | YY_HEX { $$.s_addr = htonl($1); } - | YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$); } - | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; +ipmask: ipv4 { $$ = count4bits($1.s_addr); } + | YY_HEX { $$ = count4bits(htonl($1)); } + | YY_NUMBER { $$ = $1; } + | YY_IPV6 { $$ = count6bits($1.i6); } + | maskopts { $$ = $1; } + ; + +maskopts: + IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { ifpflag = FRI_BROADCAST; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_NETWORK; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_NETMASKED; - } else + } else { YYERROR; + } + $$ = 0; } | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { - $$.s_addr = 0; ifpflag = FRI_PEERADDR; - } else + } else { YYERROR; + } + $$ = 0; } + | YY_NUMBER { $$ = $1; } ; -ipv6mask: - YY_NUMBER { ntomask(6, $1, $$.i6); } - | IPFY_BROADCAST { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else - YYERROR; - } - | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else +hostname: + ipv4 { $$.adr.in4 = $1; + if (frc->fr_family == AF_INET6) YYERROR; + $$.f = AF_INET; + yyexpectaddr = 2; } - | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else + | YY_NUMBER { if (frc->fr_family == AF_INET6) YYERROR; + $$.adr.in4_addr = $1; + $$.f = AF_INET; + yyexpectaddr = 2; } - | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { - bzero(&$$, sizeof($$)); - ifpflag = FRI_BROADCAST; - } else + | YY_HEX { if (frc->fr_family == AF_INET6) YYERROR; + $$.adr.in4_addr = $1; + $$.f = AF_INET; + yyexpectaddr = 2; } - ; - -hostname: - ipv4 { $$ = $1; } - | YY_NUMBER { $$.s_addr = $1; } - | YY_HEX { $$.s_addr = $1; } - | YY_STR { $$.s_addr = lookuphost($1); + | YY_STR { if (lookuphost($1, &$$.adr) == 0) + $$.f = AF_INET; free($1); + yyexpectaddr = 2; + } + | YY_IPV6 { if (frc->fr_family == AF_INET) + YYERROR; + $$.adr = $1; + $$.f = AF_INET6; + yyexpectaddr = 2; } ; addrlist: ipaddr { $$ = newalist(NULL); - bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); - bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } - | addrlist ',' ipaddr - { $$ = newalist($1); - bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); - bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } + | ipaddr ',' { yyexpectaddr = 1; } addrlist + { $$ = newalist($4); + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } ; pool: IPFY_POOL { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } @@ -1010,53 +1195,70 @@ hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } poollist: ipaddr { $$ = newalist(NULL); - bcopy(&($1.a), &($$->al_i6addr), sizeof($1.a)); - bcopy(&($1.m), &($$->al_i6mask), sizeof($1.m)); } + $$->al_family = $1.f; + $$->al_i6addr = $1.a; + $$->al_i6mask = $1.m; + } | '!' ipaddr { $$ = newalist(NULL); $$->al_not = 1; - bcopy(&($2.a), &($$->al_i6addr), sizeof($2.a)); - bcopy(&($2.m), &($$->al_i6mask), sizeof($2.m)); } + $$->al_family = $2.f; + $$->al_i6addr = $2.a; + $$->al_i6mask = $2.m; + } | poollist ',' ipaddr { $$ = newalist($1); - bcopy(&($3.a), &($$->al_i6addr), sizeof($3.a)); - bcopy(&($3.m), &($$->al_i6mask), sizeof($3.m)); } + $$->al_family = $3.f; + $$->al_i6addr = $3.a; + $$->al_i6mask = $3.m; + } | poollist ',' '!' ipaddr { $$ = newalist($1); $$->al_not = 1; - bcopy(&($4.a), &($$->al_i6addr), sizeof($4.a)); - bcopy(&($4.m), &($$->al_i6mask), sizeof($4.m)); } + $$->al_family = $4.f; + $$->al_i6addr = $4.a; + $$->al_i6mask = $4.m; + } ; port: IPFY_PORT { yyexpectaddr = 0; yycont = NULL; + if (frc->fr_proto != 0 && + frc->fr_proto != IPPROTO_UDP && + frc->fr_proto != IPPROTO_TCP) + yyerror("port use incorrect"); } ; portc: port compare { $$ = $2; - yysetdict(NULL); } + yysetdict(NULL); + } | porteq { $$ = $1; } ; porteq: port '=' { $$ = FR_EQUAL; - yysetdict(NULL); } + yysetdict(NULL); + } ; portr: IPFY_PORT { yyexpectaddr = 0; yycont = NULL; - yysetdict(NULL); } + yysetdict(NULL); + } ; portcomp: portc portnum { $$.pc = $1; $$.p1 = $2; - yyresetdict(); } + yyresetdict(); + } ; portrange: portr portnum range portnum { $$.p1 = $2; $$.pc = $3; $$.p2 = $4; - yyresetdict(); } + yyresetdict(); + } ; icmp: | itype icode @@ -1070,8 +1272,30 @@ itype: seticmptype icmptype ; seticmptype: - IPFY_ICMPTYPE { setipftype(); - yysetdict(icmptypewords); } + IPFY_ICMPTYPE { if (frc->fr_family == AF_UNSPEC) + frc->fr_family = AF_INET; + if (frc->fr_family == AF_INET && + frc->fr_type == FR_T_IPF && + frc->fr_proto != IPPROTO_ICMP) { + yyerror("proto not icmp"); + } + if (frc->fr_family == AF_INET6 && + frc->fr_type == FR_T_IPF && + frc->fr_proto != IPPROTO_ICMPV6) { + yyerror("proto not ipv6-icmp"); + } + setipftype(); + DOALL(if (fr->fr_family == AF_INET) { \ + fr->fr_ip.fi_v = 4; \ + fr->fr_mip.fi_v = 0xf; \ + } + if (fr->fr_family == AF_INET6) { \ + fr->fr_ip.fi_v = 6; \ + fr->fr_mip.fi_v = 0xf; \ + } + ) + yysetdict(NULL); + } ; icode: | seticmpcode icmpcode @@ -1146,9 +1370,18 @@ stateopt: IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) } | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ YYERROR; \ - } else \ + } else if (fr->fr_flags & FR_STLOOSE) {\ + YYERROR; \ + } else \ fr->fr_flags |= FR_STSTRICT;) } + | IPFY_LOOSE { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ + YYERROR; \ + } else if (fr->fr_flags & FR_STSTRICT){\ + YYERROR; \ + } else \ + fr->fr_flags |= FR_STLOOSE;) + } | IPFY_NEWISN { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ YYERROR; \ } else \ @@ -1162,10 +1395,32 @@ stateopt: | IPFY_AGE YY_NUMBER '/' YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ fr->fr_age[1] = $4;) } + | IPFY_ICMPHEAD groupname + { DOALL(seticmphead(&fr, $2);) + free($2); + } + | IPFY_NOLOG + { DOALL(fr->fr_nostatelog = 1;) } + | IPFY_RPC + { DOALL(fr->fr_rpc = 1;) } + | IPFY_RPC IPFY_IN YY_STR + { DOALL(fr->fr_rpc = 1;) } + | IPFY_MAX_SRCS YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_nodes = $2;) } + | IPFY_MAX_PER_SRC YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ + fr->fr_srctrack.ht_netmask = \ + fr->fr_family == AF_INET ? 32: 128;) + } + | IPFY_MAX_PER_SRC YY_NUMBER '/' YY_NUMBER + { DOALL(fr->fr_srctrack.ht_max_per_node = $2; \ + fr->fr_srctrack.ht_netmask = $4;) + } ; portnum: - servicename { if (getport(frc, $1, &($$)) == -1) + servicename { if (getport(frc, $1, + &($$), NULL) == -1) yyerror("service unknown"); $$ = ntohs($$); free($1); @@ -1188,14 +1443,14 @@ withopt: | notwith opttype { DOALL(fr->fr_mflx |= $2;) } | ipopt ipopts { yyresetdict(); } | notwith ipopt ipopts { yyresetdict(); } - | startv6hdrs ipv6hdrs { yyresetdict(); } + | startv6hdr ipv6hdrs { yyresetdict(); } ; ipopt: IPFY_OPT { yysetdict(ipv4optwords); } ; -startv6hdrs: - IPF6_V6HDRS { if (use_inet6 == 0) +startv6hdr: + IPFY_V6HDR { if (frc->fr_family != AF_INET6) yyerror("only available with IPv6"); yysetdict(ipv6optwords); } @@ -1222,9 +1477,18 @@ opttype: | IPFY_BROADCAST { $$ = FI_BROADCAST; } | IPFY_STATE { $$ = FI_STATE; } | IPFY_OOW { $$ = FI_OOW; } + | IPFY_AH { $$ = FI_AH; } + | IPFY_V6HDRS { $$ = FI_V6EXTHDR; } ; ipopts: optlist { DOALL(fr->fr_mip.fi_optmsk |= $1; + if (fr->fr_family == AF_UNSPEC) { + fr->fr_family = AF_INET; + fr->fr_ip.fi_v = 4; + fr->fr_mip.fi_v = 0xf; + } else if (fr->fr_family != AF_INET) { + YYERROR; + } if (!nowith) fr->fr_ip.fi_optmsk |= $1;) } @@ -1264,22 +1528,11 @@ seclevel: ; icmptype: - YY_NUMBER { $$ = $1; } - | IPFY_ICMPT_UNR { $$ = ICMP_UNREACH; } - | IPFY_ICMPT_ECHO { $$ = ICMP_ECHO; } - | IPFY_ICMPT_ECHOR { $$ = ICMP_ECHOREPLY; } - | IPFY_ICMPT_SQUENCH { $$ = ICMP_SOURCEQUENCH; } - | IPFY_ICMPT_REDIR { $$ = ICMP_REDIRECT; } - | IPFY_ICMPT_TIMEX { $$ = ICMP_TIMXCEED; } - | IPFY_ICMPT_PARAMP { $$ = ICMP_PARAMPROB; } - | IPFY_ICMPT_TIMEST { $$ = ICMP_TSTAMP; } - | IPFY_ICMPT_TIMESTREP { $$ = ICMP_TSTAMPREPLY; } - | IPFY_ICMPT_INFOREQ { $$ = ICMP_IREQ; } - | IPFY_ICMPT_INFOREP { $$ = ICMP_IREQREPLY; } - | IPFY_ICMPT_MASKREQ { $$ = ICMP_MASKREQ; } - | IPFY_ICMPT_MASKREP { $$ = ICMP_MASKREPLY; } - | IPFY_ICMPT_ROUTERAD { $$ = ICMP_ROUTERADVERT; } - | IPFY_ICMPT_ROUTERSOL { $$ = ICMP_ROUTERSOLICIT; } + YY_NUMBER { $$ = $1; } + | YY_STR { $$ = geticmptype(frc->fr_family, $1); + if ($$ == -1) + yyerror("unrecognised icmp type"); + } ; icmpcode: @@ -1314,7 +1567,8 @@ opt: | IPFY_IPOPT_SEC { $$ = getoptbyvalue(IPOPT_SECURITY); } | IPFY_IPOPT_LSRR { $$ = getoptbyvalue(IPOPT_LSRR); } | IPFY_IPOPT_ESEC { $$ = getoptbyvalue(IPOPT_E_SEC); } - | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } + | IPFY_IPOPT_CIPSO { $$ = getoptbyvalue(IPOPT_CIPSO); } + | IPFY_IPOPT_CIPSO doi { $$ = getoptbyvalue(IPOPT_CIPSO); } | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); } | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); } | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); } @@ -1329,6 +1583,13 @@ opt: | IPFY_IPOPT_UMP { $$ = getoptbyvalue(IPOPT_UMP); } | setsecclass secname { DOALL(fr->fr_mip.fi_secmsk |= $2; + if (fr->fr_family == AF_UNSPEC) { + fr->fr_family = AF_INET; + fr->fr_ip.fi_v = 4; + fr->fr_mip.fi_v = 0xf; + } else if (fr->fr_family != AF_INET) { + YYERROR; + } if (!nowith) fr->fr_ip.fi_secmsk |= $2;) $$ = 0; @@ -1337,7 +1598,15 @@ opt: ; setsecclass: - IPFY_SECCLASS { yysetdict(ipv4secwords); } + IPFY_SECCLASS { yysetdict(ipv4secwords); } + ; + +doi: IPFY_DOI YY_NUMBER { DOALL(fr->fr_doimask = 0xffffffff; \ + if (!nowith) \ + fr->fr_doi = $2;) } + | IPFY_DOI YY_HEX { DOALL(fr->fr_doimask = 0xffffffff; \ + if (!nowith) \ + fr->fr_doi = $2;) } ; ipv6hdr: @@ -1463,7 +1732,7 @@ ipv4: ipv4_24 '.' YY_NUMBER %% -static struct wordtab ipfwords[95] = { +static struct wordtab ipfwords[] = { { "age", IPFY_AGE }, { "ah", IPFY_AH }, { "all", IPFY_ALL }, @@ -1481,10 +1750,16 @@ static struct wordtab ipfwords[95] = { #endif { "call", IPFY_CALL }, { "code", IPFY_ICMPCODE }, + { "comment", IPFY_COMMENT }, { "count", IPFY_COUNT }, + { "decapsulate", IPFY_DECAPS }, + { "dstlist", IPFY_DSTLIST }, + { "doi", IPFY_DOI }, { "dup-to", IPFY_DUPTO }, { "eq", YY_CMP_EQ }, { "esp", IPFY_ESP }, + { "exp", IPFY_IPFEXPR }, + { "family", IPFY_FAMILY }, { "fastroute", IPFY_FROUTE }, { "first", IPFY_FIRST }, { "flags", IPFY_FLAGS }, @@ -1497,20 +1772,27 @@ static struct wordtab ipfwords[95] = { { "gt", YY_CMP_GT }, { "head", IPFY_HEAD }, { "icmp", IPFY_ICMP }, + { "icmp-head", IPFY_ICMPHEAD }, { "icmp-type", IPFY_ICMPTYPE }, { "in", IPFY_IN }, { "in-via", IPFY_INVIA }, + { "inet", IPFY_INET }, + { "inet6", IPFY_INET6 }, { "ipopt", IPFY_IPOPTS }, { "ipopts", IPFY_IPOPTS }, { "keep", IPFY_KEEP }, + { "l5-as", IPFY_L5AS }, { "le", YY_CMP_LE }, { "level", IPFY_LEVEL }, { "limit", IPFY_LIMIT }, { "log", IPFY_LOG }, + { "loose", IPFY_LOOSE }, { "lowttl", IPFY_LOWTTL }, { "lt", YY_CMP_LT }, { "mask", IPFY_MASK }, { "match-tag", IPFY_MATCHTAG }, + { "max-per-src", IPFY_MAX_PER_SRC }, + { "max-srcs", IPFY_MAX_SRCS }, { "mbcast", IPFY_MBCAST }, { "mcast", IPFY_MULTICAST }, { "multicast", IPFY_MULTICAST }, @@ -1520,6 +1802,7 @@ static struct wordtab ipfwords[95] = { { "newisn", IPFY_NEWISN }, { "no", IPFY_NO }, { "no-icmp-err", IPFY_NOICMPERR }, + { "nolog", IPFY_NOLOG }, { "nomatch", IPFY_NOMATCH }, { "now", IPFY_NOW }, { "not", IPFY_NOT }, @@ -1540,7 +1823,10 @@ static struct wordtab ipfwords[95] = { { "return-icmp-as-dest", IPFY_RETICMPASDST }, { "return-rst", IPFY_RETRST }, { "route-to", IPFY_ROUTETO }, + { "rule-ttl", IPFY_RULETTL }, + { "rpc", IPFY_RPC }, { "sec-class", IPFY_SECCLASS }, + { "set", IPFY_SET }, { "set-tag", IPFY_SETTAG }, { "skip", IPFY_SKIP }, { "short", IPFY_SHORT }, @@ -1554,19 +1840,20 @@ static struct wordtab ipfwords[95] = { { "to", IPFY_TO }, { "ttl", IPFY_TTL }, { "udp", IPFY_UDP }, - { "v6hdrs", IPF6_V6HDRS }, + { "v6hdr", IPFY_V6HDR }, + { "v6hdrs", IPFY_V6HDRS }, { "with", IPFY_WITH }, { NULL, 0 } }; -static struct wordtab addrwords[4] = { +static struct wordtab addrwords[] = { { "any", IPFY_ANY }, { "hash", IPFY_HASH }, { "pool", IPFY_POOL }, { NULL, 0 } }; -static struct wordtab maskwords[5] = { +static struct wordtab maskwords[] = { { "broadcast", IPFY_BROADCAST }, { "netmasked", IPFY_NETMASKED }, { "network", IPFY_NETWORK }, @@ -1574,26 +1861,7 @@ static struct wordtab maskwords[5] = { { NULL, 0 } }; -static struct wordtab icmptypewords[16] = { - { "echo", IPFY_ICMPT_ECHO }, - { "echorep", IPFY_ICMPT_ECHOR }, - { "inforeq", IPFY_ICMPT_INFOREQ }, - { "inforep", IPFY_ICMPT_INFOREP }, - { "maskrep", IPFY_ICMPT_MASKREP }, - { "maskreq", IPFY_ICMPT_MASKREQ }, - { "paramprob", IPFY_ICMPT_PARAMP }, - { "redir", IPFY_ICMPT_REDIR }, - { "unreach", IPFY_ICMPT_UNR }, - { "routerad", IPFY_ICMPT_ROUTERAD }, - { "routersol", IPFY_ICMPT_ROUTERSOL }, - { "squench", IPFY_ICMPT_SQUENCH }, - { "timest", IPFY_ICMPT_TIMEST }, - { "timestrep", IPFY_ICMPT_TIMESTREP }, - { "timex", IPFY_ICMPT_TIMEX }, - { NULL, 0 }, -}; - -static struct wordtab icmpcodewords[17] = { +static struct wordtab icmpcodewords[] = { { "cutoff-preced", IPFY_ICMPC_CUTPRE }, { "filter-prohib", IPFY_ICMPC_FLTPRO }, { "isolate", IPFY_ICMPC_ISOLATE }, @@ -1613,7 +1881,7 @@ static struct wordtab icmpcodewords[17] = { { NULL, 0 }, }; -static struct wordtab ipv4optwords[25] = { +static struct wordtab ipv4optwords[] = { { "addext", IPFY_IPOPT_ADDEXT }, { "cipso", IPFY_IPOPT_CIPSO }, { "dps", IPFY_IPOPT_DPS }, @@ -1641,7 +1909,7 @@ static struct wordtab ipv4optwords[25] = { { NULL, 0 }, }; -static struct wordtab ipv4secwords[9] = { +static struct wordtab ipv4secwords[] = { { "confid", IPFY_SEC_CONF }, { "reserv-1", IPFY_SEC_RSV1 }, { "reserv-2", IPFY_SEC_RSV2 }, @@ -1653,7 +1921,7 @@ static struct wordtab ipv4secwords[9] = { { NULL, 0 }, }; -static struct wordtab ipv6optwords[9] = { +static struct wordtab ipv6optwords[] = { { "dstopts", IPFY_IPV6OPT_DSTOPTS }, { "esp", IPFY_IPV6OPT_ESP }, { "frag", IPFY_IPV6OPT_FRAG }, @@ -1665,7 +1933,7 @@ static struct wordtab ipv6optwords[9] = { { NULL, 0 }, }; -static struct wordtab logwords[33] = { +static struct wordtab logwords[] = { { "kern", IPFY_FAC_KERN }, { "user", IPFY_FAC_USER }, { "mail", IPFY_FAC_MAIL }, @@ -1751,7 +2019,7 @@ FILE *fp; ipffd = fd; for (i = 0; i <= IPL_LOGMAX; i++) - ipfioctl[i] = iocfuncs[i]; + ipfioctls[i] = iocfuncs[i]; ipfaddfunc = addfunc; if (feof(fp)) @@ -1779,23 +2047,29 @@ static void newrule() { frentry_t *frn; - frn = (frentry_t *)calloc(1, sizeof(frentry_t)); + frn = allocfr(); for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next) ; - if (fr != NULL) + if (fr != NULL) { fr->fr_next = frn; - if (frtop == NULL) + frn->fr_pnext = &fr->fr_next; + } + if (frtop == NULL) { frtop = frn; + frn->fr_pnext = &frtop; + } fr = frn; frc = frn; fr->fr_loglevel = 0xffff; fr->fr_isc = (void *)-1; fr->fr_logtag = FR_NOLOGTAG; fr->fr_type = FR_T_NONE; - if (use_inet6 != 0) - fr->fr_v = 6; - else - fr->fr_v = 4; + fr->fr_flineno = yylineNum; + + if (use_inet6 == 1) + fr->fr_family = AF_INET6; + else if (use_inet6 == -1) + fr->fr_family = AF_INET; nrules = 1; } @@ -1808,7 +2082,13 @@ static void setipftype() fr->fr_type = FR_T_IPF; fr->fr_data = (void *)calloc(sizeof(fripf_t), 1); fr->fr_dsize = sizeof(fripf_t); - fr->fr_ip.fi_v = frc->fr_v; + fr->fr_family = frc->fr_family; + if (fr->fr_family == AF_INET) { + fr->fr_ip.fi_v = 4; + } + else if (fr->fr_family == AF_INET6) { + fr->fr_ip.fi_v = 6; + } fr->fr_mip.fi_v = 0xf; fr->fr_ipf->fri_sifpidx = -1; fr->fr_ipf->fri_difpidx = -1; @@ -1831,10 +2111,13 @@ static frentry_t *addrule() count = nrules; f = f2; for (f1 = frc; count > 0; count--, f1 = f1->fr_next) { - f->fr_next = (frentry_t *)calloc(sizeof(*f), 1); + f->fr_next = allocfr(); + if (f->fr_next == NULL) + return NULL; + f->fr_next->fr_pnext = &f->fr_next; added++; f = f->fr_next; - bcopy(f1, f, sizeof(*f)); + *f = *f1; f->fr_next = NULL; if (f->fr_caddr != NULL) { f->fr_caddr = malloc(f->fr_dsize); @@ -1846,10 +2129,11 @@ static frentry_t *addrule() } -static u_32_t lookuphost(name) -char *name; +static int +lookuphost(name, addrp) + char *name; + i6addr_t *addrp; { - u_32_t addr; int i; hashed = 0; @@ -1857,19 +2141,20 @@ char *name; dynamic = -1; for (i = 0; i < 4; i++) { - if (strncmp(name, frc->fr_ifnames[i], - sizeof(frc->fr_ifnames[i])) == 0) { + if (fr->fr_ifnames[i] == -1) + continue; + if (strcmp(name, fr->fr_names + fr->fr_ifnames[i]) == 0) { ifpflag = FRI_DYNAMIC; - dynamic = i; - return 0; + dynamic = addname(&fr, name); + return 1; } } - if (gethost(name, &addr) == -1) { + if (gethost(AF_INET, name, addrp) == -1) { fprintf(stderr, "unknown name \"%s\"\n", name); - return 0; + return -1; } - return addr; + return 0; } @@ -1891,7 +2176,7 @@ char *phrase; fprintf(stderr, "cannot mix IPF and BPF matching\n"); return; } - fr->fr_v = v; + fr->fr_family = vtof(v); fr->fr_type = FR_T_BPFOPC; if (!strncmp(phrase, "0x", 2)) { @@ -1986,8 +2271,9 @@ alist_t *ptr; } -static int makepool(list) -alist_t *list; +static int +makepool(list) + alist_t *list; { ip_pool_node_t *n, *top; ip_pool_t pool; @@ -1999,10 +2285,30 @@ alist_t *list; top = calloc(1, sizeof(*top)); if (top == NULL) return 0; - + for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { - n->ipn_addr.adf_addr.in4.s_addr = a->al_1; - n->ipn_mask.adf_addr.in4.s_addr = a->al_2; + if (use_inet6 == 1) { +#ifdef AF_INET6 + n->ipn_addr.adf_family = AF_INET6; + n->ipn_addr.adf_addr = a->al_i6addr; + n->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + 16; + n->ipn_mask.adf_family = AF_INET6; + n->ipn_mask.adf_addr = a->al_i6mask; + n->ipn_mask.adf_len = offsetof(addrfamily_t, + adf_addr) + 16; + +#endif + } else { + n->ipn_addr.adf_family = AF_INET; + n->ipn_addr.adf_addr.in4.s_addr = a->al_1; + n->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + 4; + n->ipn_mask.adf_family = AF_INET; + n->ipn_mask.adf_addr.in4.s_addr = a->al_2; + n->ipn_mask.adf_len = offsetof(addrfamily_t, + adf_addr) + 4; + } n->ipn_info = a->al_not; if (a->al_next != NULL) { n->ipn_next = calloc(1, sizeof(*n)); @@ -2013,7 +2319,7 @@ alist_t *list; bzero((char *)&pool, sizeof(pool)); pool.ipo_unit = IPL_LOGIPF; pool.ipo_list = top; - num = load_pool(&pool, ipfioctl[IPL_LOGLOOKUP]); + num = load_pool(&pool, ipfioctls[IPL_LOGLOOKUP]); while ((n = top) != NULL) { top = n->ipn_next; @@ -2036,10 +2342,17 @@ alist_t *list; top = calloc(1, sizeof(*top)); if (top == NULL) return 0; - + for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { - n->ipe_addr.in4_addr = a->al_1; - n->ipe_mask.in4_addr = a->al_2; + if (a->al_family == AF_INET6) { + n->ipe_family = AF_INET6; + n->ipe_addr = a->al_i6addr; + n->ipe_mask = a->al_i6mask; + } else { + n->ipe_family = AF_INET; + n->ipe_addr.in4_addr = a->al_1; + n->ipe_mask.in4_addr = a->al_2; + } n->ipe_value = 0; if (a->al_next != NULL) { n->ipe_next = calloc(1, sizeof(*n)); @@ -2052,7 +2365,7 @@ alist_t *list; iph.iph_type = IPHASH_LOOKUP; *iph.iph_name = '\0'; - if (load_hash(&iph, top, ipfioctl[IPL_LOGLOOKUP]) == 0) + if (load_hash(&iph, top, ipfioctls[IPL_LOGLOOKUP]) == 0) sscanf(iph.iph_name, "%u", &num); else num = 0; @@ -2065,7 +2378,7 @@ alist_t *list; } -void ipf_addrule(fd, ioctlfunc, ptr) +int ipf_addrule(fd, ioctlfunc, ptr) int fd; ioctlfunc_t ioctlfunc; void *ptr; @@ -2075,7 +2388,7 @@ void *ptr; ipfobj_t obj; if (ptr == NULL) - return; + return 0; fr = ptr; add = 0; @@ -2083,7 +2396,7 @@ void *ptr; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(*fr); + obj.ipfo_size = fr->fr_size; obj.ipfo_type = IPFOBJ_FRENTRY; obj.ipfo_ptr = ptr; @@ -2118,8 +2431,11 @@ void *ptr; if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(SIOCZRLST)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(zero rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } else { #ifdef USE_QUAD_T @@ -2134,19 +2450,26 @@ void *ptr; } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { - if ((opts & OPT_DONOTHING) != 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(delete rule)"); + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(delete rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { - if (!(opts & OPT_DONOTHING)) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(add/insert rule)"); + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(add/insert rule)", + fr->fr_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } + return 0; } static void setsyslog() @@ -2168,9 +2491,16 @@ frentry_t *fr; { frentry_t *f; - for (f = frold; f != NULL; f = f->fr_next) - if (strncmp(f->fr_grhead, fr->fr_group, FR_GROUPLEN) == 0) + for (f = frold; f != NULL; f = f->fr_next) { + if (f->fr_grhead == -1 && fr->fr_group == -1) break; + if (f->fr_grhead == -1 || fr->fr_group == -1) + continue; + if (strcmp(f->fr_names + f->fr_grhead, + fr->fr_names + fr->fr_group) == 0) + break; + } + if (f == NULL) return; @@ -2183,8 +2513,8 @@ frentry_t *fr; if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) return; - if (fr->fr_v == 0 && f->fr_v != 0) - fr->fr_v = f->fr_v; + if (fr->fr_family == 0 && f->fr_family != 0) + fr->fr_family = f->fr_family; if (fr->fr_mproto == 0 && f->fr_mproto != 0) fr->fr_mproto = f->fr_mproto; @@ -2192,6 +2522,218 @@ frentry_t *fr; fr->fr_proto = f->fr_proto; if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) && - ((f->fr_flx & FI_TCPUDP) != 0)) + ((f->fr_flx & FI_TCPUDP) != 0)) { fr->fr_flx |= FI_TCPUDP; + fr->fr_mflx |= FI_TCPUDP; + } +} + + +static void doipfexpr(line) +char *line; +{ + int *array; + char *error; + + array = parseipfexpr(line, &error); + if (array == NULL) { + fprintf(stderr, "%s:", error); + yyerror("error parsing ipf matching expression"); + return; + } + + fr->fr_type = FR_T_IPFEXPR; + fr->fr_data = array; + fr->fr_dsize = array[0] * sizeof(*array); +} + + +static void do_tuneint(varname, value) +char *varname; +int value; +{ + char buffer[80]; + + strncpy(buffer, varname, 60); + buffer[59] = '\0'; + strcat(buffer, "="); + sprintf(buffer, "%u", value); + ipf_dotuning(ipffd, buffer, ioctl); +} + + +static void do_tunestr(varname, value) +char *varname, *value; +{ + + if (!strcasecmp(value, "true")) { + do_tuneint(varname, 1); + } else if (!strcasecmp(value, "false")) { + do_tuneint(varname, 0); + } else { + yyerror("did not find true/false where expected"); + } +} + + +static void setifname(frp, idx, name) +frentry_t **frp; +int idx; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_ifnames[idx] = pos; +} + + +static int addname(frp, name) +frentry_t **frp; +char *name; +{ + frentry_t *f; + int nlen; + int pos; + + nlen = strlen(name) + 1; + f = realloc(*frp, (*frp)->fr_size + nlen); + if (*frp == frc) + frc = f; + *frp = f; + if (f == NULL) + return -1; + if (f->fr_pnext != NULL) + *f->fr_pnext = f; + f->fr_size += nlen; + pos = f->fr_namelen; + f->fr_namelen += nlen; + strcpy(f->fr_names + pos, name); + f->fr_names[f->fr_namelen] = '\0'; + return pos; +} + + +static frentry_t *allocfr() +{ + frentry_t *fr; + + fr = calloc(1, sizeof(*fr)); + if (fr != NULL) { + fr->fr_size = sizeof(*fr); + fr->fr_comment = -1; + fr->fr_group = -1; + fr->fr_grhead = -1; + fr->fr_icmphead = -1; + fr->fr_ifnames[0] = -1; + fr->fr_ifnames[1] = -1; + fr->fr_ifnames[2] = -1; + fr->fr_ifnames[3] = -1; + fr->fr_tif.fd_name = -1; + fr->fr_rif.fd_name = -1; + fr->fr_dif.fd_name = -1; + } + return fr; +} + + +static void setgroup(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_group = pos; +} + + +static void setgrhead(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_grhead = pos; +} + + +static void seticmphead(frp, name) +frentry_t **frp; +char *name; +{ + int pos; + + pos = addname(frp, name); + if (pos == -1) + return; + (*frp)->fr_icmphead = pos; +} + + +static void +build_dstaddr_af(fp, ptr) + frentry_t *fp; + void *ptr; +{ + struct ipp_s *ipp = ptr; + frentry_t *f = fp; + + if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { + ipp->f = f->fr_family; + ipp->v = f->fr_ip.fi_v; + } + if (ipp->f == AF_INET) + ipp->v = 4; + else if (ipp->f == AF_INET6) + ipp->v = 6; + + for (; f != NULL; f = f->fr_next) { + f->fr_ip.fi_dst = ipp->a; + f->fr_mip.fi_dst = ipp->m; + f->fr_family = ipp->f; + f->fr_ip.fi_v = ipp->v; + f->fr_mip.fi_v = 0xf; + f->fr_datype = ipp->type; + if (ipp->ifpos != -1) + f->fr_ipf->fri_difpidx = ipp->ifpos; + } + fr = NULL; +} + + +static void +build_srcaddr_af(fp, ptr) + frentry_t *fp; + void *ptr; +{ + struct ipp_s *ipp = ptr; + frentry_t *f = fp; + + if (f->fr_family != AF_UNSPEC && ipp->f == AF_UNSPEC) { + ipp->f = f->fr_family; + ipp->v = f->fr_ip.fi_v; + } + if (ipp->f == AF_INET) + ipp->v = 4; + else if (ipp->f == AF_INET6) + ipp->v = 6; + + for (; f != NULL; f = f->fr_next) { + f->fr_ip.fi_src = ipp->a; + f->fr_mip.fi_src = ipp->m; + f->fr_family = ipp->f; + f->fr_ip.fi_v = ipp->v; + f->fr_mip.fi_v = 0xf; + f->fr_satype = ipp->type; + f->fr_ipf->fri_sifpidx = ipp->ifpos; + } + fr = NULL; } diff --git a/contrib/ipfilter/tools/ipfcomp.c b/contrib/ipfilter/tools/ipfcomp.c index e00fe84a9af3..eba28ceb1d51 100644 --- a/contrib/ipfilter/tools/ipfcomp.c +++ b/contrib/ipfilter/tools/ipfcomp.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2005 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfcomp.c,v 1.24.2.7 2007/05/01 22:15:00 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include "ipf.h" @@ -63,7 +63,7 @@ static FILE *cfile = NULL; * required. */ void printc(fr) -frentry_t *fr; + frentry_t *fr; { fripf_t *ipf; u_long *ulp; @@ -71,7 +71,7 @@ frentry_t *fr; FILE *fp; int i; - if (fr->fr_v != 4) + if (fr->fr_family == 6) return; if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE)) return; @@ -87,7 +87,7 @@ frentry_t *fr; fp = cfile; if (count == 0) { fprintf(fp, "/*\n"); - fprintf(fp, "* Copyright (C) 1993-2000 by Darren Reed.\n"); + fprintf(fp, "* Copyright (C) 2012 by Darren Reed.\n"); fprintf(fp, "*\n"); fprintf(fp, "* Redistribution and use in source and binary forms are permitted\n"); fprintf(fp, "* provided that this notice is preserved and due credit is given\n"); @@ -136,6 +136,9 @@ frentry_t *fr; fprintf(fp, "#endif /* _KERNEL */\n"); fprintf(fp, "\n"); fprintf(fp, "#ifdef IPFILTER_COMPILED\n"); + fprintf(fp, "\n"); + fprintf(fp, "extern ipf_main_softc_t ipfmain;\n"); + fprintf(fp, "\n"); } addrule(fp, fr); @@ -162,12 +165,14 @@ static frgroup_t *groups = NULL; static void addrule(fp, fr) -FILE *fp; -frentry_t *fr; + FILE *fp; + frentry_t *fr; { frentry_t *f, **fpp; frgroup_t *g; u_long *ulp; + char *ghead; + char *gname; char *and; int i; @@ -180,8 +185,10 @@ frentry_t *fr; } f->fr_next = NULL; + gname = FR_NAME(fr, fr_group); + for (g = groups; g != NULL; g = g->fg_next) - if ((strncmp(g->fg_name, f->fr_group, FR_GROUPLEN) == 0) && + if ((strncmp(g->fg_name, gname, FR_GROUPLEN) == 0) && (g->fg_flags == (f->fr_flags & FR_INOUT))) break; @@ -190,7 +197,7 @@ frentry_t *fr; g->fg_next = groups; groups = g; g->fg_head = f; - bcopy(f->fr_group, g->fg_name, FR_GROUPLEN); + strncpy(g->fg_name, gname, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } @@ -219,10 +226,10 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", g->fg_ref++; - if (f->fr_grhead != 0) { + if (f->fr_grhead != -1) { + ghead = FR_NAME(f, fr_grhead); for (g = groups; g != NULL; g = g->fg_next) - if ((strncmp(g->fg_name, f->fr_grhead, - FR_GROUPLEN) == 0) && + if ((strncmp(g->fg_name, ghead, FR_GROUPLEN) == 0) && g->fg_flags == (f->fr_flags & FR_INOUT)) break; if (g == NULL) { @@ -230,7 +237,7 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", g->fg_next = groups; groups = g; g->fg_head = f; - bcopy(f->fr_grhead, g->fg_name, FR_GROUPLEN); + strncpy(g->fg_name, ghead, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } @@ -239,7 +246,7 @@ static u_long ipf%s_rule_data_%s_%u[] = {\n", int intcmp(c1, c2) -const void *c1, *c2; + const void *c1, *c2; { const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2; @@ -251,17 +258,17 @@ const void *c1, *c2; static void indent(fp, in) -FILE *fp; -int in; + FILE *fp; + int in; { for (; in; in--) fputc('\t', fp); } static void printeq(fp, var, m, max, v) -FILE *fp; -char *var; -int m, max, v; + FILE *fp; + char *var; + int m, max, v; { if (m == max) fprintf(fp, "%s == %#x) {\n", var, v); @@ -276,9 +283,9 @@ int m, max, v; * v - required address */ static void printipeq(fp, var, fl, m, v) -FILE *fp; -char *var; -int fl, m, v; + FILE *fp; + char *var; + int fl, m, v; { if (m == 0xffffffff) fprintf(fp, "%s ", var); @@ -290,9 +297,9 @@ int fl, m, v; void emit(num, dir, v, fr) -int num, dir; -void *v; -frentry_t *fr; + int num, dir; + void *v; + frentry_t *fr; { u_int incnt, outcnt; frgroup_t *g; @@ -342,8 +349,8 @@ frentry_t *fr; static void emitheader(grp, incount, outcount) -frgroup_t *grp; -u_int incount, outcount; + frgroup_t *grp; + u_int incount, outcount; { static FILE *fph = NULL; frgroup_t *g; @@ -434,11 +441,11 @@ int ipfrule_remove()\n\ static void emitGroup(num, dir, v, fr, group, incount, outcount) -int num, dir; -void *v; -frentry_t *fr; -char *group; -u_int incount, outcount; + int num, dir; + void *v; + frentry_t *fr; + char *group; + u_int incount, outcount; { static FILE *fp = NULL; static int header[2] = { 0, 0 }; @@ -514,9 +521,8 @@ u_int incount, outcount; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } - fprintf(fp, - "(frentry_t *)&in_rule_%s_%d", - f->fr_group, i); + fprintf(fp, "(frentry_t *)&in_rule_%s_%d", + FR_NAME(f, fr_group), i); if (i + 1 < incount) fprintf(fp, ", "); i++; @@ -534,9 +540,8 @@ u_int incount, outcount; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } - fprintf(fp, - "(frentry_t *)&out_rule_%s_%d", - f->fr_group, i); + fprintf(fp, "(frentry_t *)&out_rule_%s_%d", + FR_NAME(f, fr_group), i); if (i + 1 < outcount) fprintf(fp, ", "); i++; @@ -586,7 +591,7 @@ u_int incount, outcount; switch(m[i].c) { case FRC_IFN : - if (*fr->fr_ifname) + if (fr->fr_ifnames[0] != -1) m[i].s = 1; break; case FRC_V : @@ -940,11 +945,11 @@ u_int incount, outcount; if (fr->fr_flags & FR_QUICK) { fprintf(fp, "return (frentry_t *)&%s_rule_%s_%d;\n", fr->fr_flags & FR_INQUE ? "in" : "out", - fr->fr_group, num); + FR_NAME(fr, fr_group), num); } else { fprintf(fp, "fr = (frentry_t *)&%s_rule_%s_%d;\n", fr->fr_flags & FR_INQUE ? "in" : "out", - fr->fr_group, num); + FR_NAME(fr, fr_group), num); } if (n == NULL) n = (mc_t *)malloc(sizeof(*n) * FRC_MAX); @@ -954,7 +959,7 @@ u_int incount, outcount; void printC(dir) -int dir; + int dir; { static mc_t *m = NULL; frgroup_t *g; @@ -977,10 +982,10 @@ int dir; * Now print out code to implement all of the rules. */ static void printCgroup(dir, top, m, group) -int dir; -frentry_t *top; -mc_t *m; -char *group; + int dir; + frentry_t *top; + mc_t *m; + char *group; { frentry_t *fr, *fr1; int i, n, rn; @@ -1027,13 +1032,14 @@ char *group; continue; if ((n & 0x0001) && - !strcmp(fr1->fr_ifname, fr->fr_ifname)) { + !strcmp(fr1->fr_names + fr1->fr_ifnames[0], + fr->fr_names + fr->fr_ifnames[0])) { m[FRC_IFN].e++; m[FRC_IFN].n++; } else n &= ~0x0001; - if ((n & 0x0002) && (fr1->fr_v == fr->fr_v)) { + if ((n & 0x0002) && (fr1->fr_family == fr->fr_family)) { m[FRC_V].e++; m[FRC_V].n++; } else @@ -1226,10 +1232,10 @@ char *group; } static void printhooks(fp, in, out, grp) -FILE *fp; -int in; -int out; -frgroup_t *grp; + FILE *fp; + int in; + int out; + frgroup_t *grp; { frentry_t *fr; char *group; @@ -1237,7 +1243,7 @@ frgroup_t *grp; char *instr; group = grp->fg_name; - dogrp = *group ? 1 : 0; + dogrp = 0; if (in && out) { fprintf(stderr, @@ -1283,18 +1289,24 @@ int ipfrule_add_%s_%s()\n", instr, group); fprintf(fp, "\ for (j = i + 1; j < max; j++)\n\ - if (strncmp(fp->fr_group,\n\ + if (strncmp(fp->fr_names + fp->fr_group,\n\ + ipf_rules_%s_%s[j]->fr_names +\n\ ipf_rules_%s_%s[j]->fr_group,\n\ FR_GROUPLEN) == 0) {\n\ + if (ipf_rules_%s_%s[j] != NULL)\n\ + ipf_rules_%s_%s[j]->fr_pnext =\n\ + &fp->fr_next;\n\ + fp->fr_pnext = &ipf_rules_%s_%s[j];\n\ fp->fr_next = ipf_rules_%s_%s[j];\n\ break;\n\ - }\n", instr, group, instr, group); + }\n", instr, group, instr, group, instr, group, + instr, group, instr, group, instr, group); if (dogrp) fprintf(fp, "\ \n\ - if (fp->fr_grhead != 0) {\n\ - fg = fr_addgroup(fp->fr_grhead, fp, FR_INQUE,\n\ - IPL_LOGIPF, 0);\n\ + if (fp->fr_grhead != -1) {\n\ + fg = fr_addgroup(fp->fr_names + fp->fr_grhead,\n\ + fp, FR_INQUE, IPL_LOGIPF, 0);\n\ if (fg != NULL)\n\ fp->fr_grp = &fg->fg_start;\n\ }\n"); @@ -1304,7 +1316,7 @@ int ipfrule_add_%s_%s()\n", instr, group); fp = &ipfrule_%s_%s;\n", instr, group); fprintf(fp, "\ bzero((char *)fp, sizeof(*fp));\n\ - fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;\n\ + fp->fr_type = FR_T_CALLFUNC_BUILTIN;\n\ fp->fr_flags = FR_%sQUE|FR_NOMATCH;\n\ fp->fr_data = (void *)ipf_rules_%s_%s[0];\n", (in != 0) ? "IN" : "OUT", instr, group); @@ -1313,9 +1325,10 @@ int ipfrule_add_%s_%s()\n", instr, group); instr, group); fprintf(fp, "\ - fp->fr_v = 4;\n\ + fp->fr_family = AF_INET;\n\ fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\ - err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);\n", + err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,\n\ + ipfmain.ipf_active, 0);\n", instr, group); fprintf(fp, "\treturn err;\n}\n"); @@ -1348,8 +1361,9 @@ int ipfrule_remove_%s_%s()\n", instr, group); }\n\ }\n\ if (err == 0)\n\ - err = frrequest(IPL_LOGIPF, SIOCDELFR,\n\ - (caddr_t)&ipfrule_%s_%s, fr_active, 0);\n", + err = frrequest(&ipfmain, IPL_LOGIPF, SIOCDELFR,\n\ + (caddr_t)&ipfrule_%s_%s,\n\ + ipfmain.ipf_active, 0);\n", instr, group, instr, group, instr, group); fprintf(fp, "\ if (err)\n\ diff --git a/contrib/ipfilter/tools/ipfs.c b/contrib/ipfilter/tools/ipfs.c index eab650a7ee36..b5484be2193c 100644 --- a/contrib/ipfilter/tools/ipfs.c +++ b/contrib/ipfilter/tools/ipfs.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -44,7 +44,7 @@ #include "netinet/ipl.h" #if !defined(lint) -static const char rcsid[] = "@(#)Id: ipfs.c,v 1.12 2003/12/01 01:56:53 darrenr Exp"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifndef IPF_SAVEDIR @@ -100,7 +100,7 @@ void usage() * Change interface names in state information saved out to disk. */ int changestateif(ifs, fname) -char *ifs, *fname; + char *ifs, *fname; { int fd, olen, nlen, rw; ipstate_save_t ips; @@ -163,7 +163,7 @@ char *ifs, *fname; * Change interface names in NAT information saved out to disk. */ int changenatif(ifs, fname) -char *ifs, *fname; + char *ifs, *fname; { int fd, olen, nlen, rw; nat_save_t ipn; @@ -198,14 +198,6 @@ char *ifs, *fname; strcpy(nat->nat_ifnames[1], s); rw = 1; } - if (!strncmp(nat->nat_ifnames[2], ifs, olen + 1)) { - strcpy(nat->nat_ifnames[2], s); - rw = 1; - } - if (!strncmp(nat->nat_ifnames[3], ifs, olen + 1)) { - strcpy(nat->nat_ifnames[3], s); - rw = 1; - } if (rw == 1) { if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); @@ -225,8 +217,8 @@ char *ifs, *fname; int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { int c, lock = -1, devfd = -1, err = 0, rw = -1, ns = -1, set = 0; char *dirname = NULL, *filename = NULL, *ifs = NULL; @@ -356,7 +348,7 @@ char *argv[]; int opendevice(ipfdev) -char *ipfdev; + char *ipfdev; { int fd = -1; @@ -374,14 +366,14 @@ char *ipfdev; void closedevice(fd) -int fd; + int fd; { close(fd); } int setlock(fd, lock) -int fd, lock; + int fd, lock; { if (opts & OPT_VERBOSE) printf("Turn lock %s\n", lock ? "on" : "off"); @@ -398,8 +390,8 @@ int fd, lock; int writestate(fd, file) -int fd; -char *file; + int fd; + char *file; { ipstate_save_t ips, *ipsp; ipfobj_t obj; @@ -450,8 +442,8 @@ char *file; int readstate(fd, file) -int fd; -char *file; + int fd; + char *file; { ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; int sfd = -1, i; @@ -567,8 +559,8 @@ freeipshead: int readnat(fd, file) -int fd; -char *file; + int fd; + char *file; { nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; ipfobj_t obj; @@ -714,8 +706,8 @@ freenathead: int writenat(fd, file) -int fd; -char *file; + int fd; + char *file; { nat_save_t *ipnp = NULL, *next = NULL; ipfobj_t obj; @@ -798,7 +790,7 @@ char *file; int writeall(dirname) -char *dirname; + char *dirname; { int fd, devfd; @@ -849,7 +841,7 @@ bad: int readall(dirname) -char *dirname; + char *dirname; { int fd, devfd; diff --git a/contrib/ipfilter/tools/ipfstat.c b/contrib/ipfilter/tools/ipfstat.c index 3c5bfdd50ac4..3261cef8e4d2 100644 --- a/contrib/ipfilter/tools/ipfstat.c +++ b/contrib/ipfilter/tools/ipfstat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -15,6 +15,7 @@ # endif #endif #include <sys/ioctl.h> +#include <ctype.h> #include <fcntl.h> #ifdef linux # include <linux/a.out.h> @@ -71,7 +72,7 @@ #if !defined(lint) static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipfstat.c,v 1.44.2.25 2007/06/30 09:48:50 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #ifdef __hpux @@ -87,7 +88,9 @@ extern int opterr; static char *filters[4] = { "ipfilter(in)", "ipfilter(out)", "ipacct(in)", "ipacct(out)" }; static int state_logging = -1; +static wordtab_t *state_fields = NULL; +int nohdrfields = 0; int opts = 0; int use_inet6 = 0; int live_kernel = 1; @@ -98,6 +101,26 @@ int nat_fd = -1; frgroup_t *grtop = NULL; frgroup_t *grtail = NULL; +char *blockreasons[FRB_MAX_VALUE + 1] = { + "packet blocked", + "log rule failure", + "pps rate exceeded", + "jumbogram", + "makefrip failed", + "cannot add state", + "IP ID update failed", + "log-or-block failed", + "decapsulate failure", + "cannot create new auth entry", + "packet queued for auth", + "buffer coalesce failure", + "buffer pullup failure", + "auth feedback", + "bad fragment", + "IPv4 NAT failure", + "IPv6 NAT failure" +}; + #ifdef STATETOP #define STSTRSIZE 80 #define STGROWSIZE 16 @@ -135,22 +158,27 @@ static int fetchfrag __P((int, int, ipfr_t *)); static void showstats __P((friostat_t *, u_32_t)); static void showfrstates __P((ipfrstat_t *, u_long)); static void showlist __P((friostat_t *)); -static void showipstates __P((ips_stat_t *)); -static void showauthstates __P((fr_authstat_t *)); +static void showstatestats __P((ips_stat_t *)); +static void showipstates __P((ips_stat_t *, int *)); +static void showauthstates __P((ipf_authstat_t *)); +static void showtqtable_live __P((int)); static void showgroups __P((friostat_t *)); static void usage __P((char *)); -static void showtqtable_live __P((int)); -static void printlivelist __P((int, int, frentry_t *, char *, char *)); -static void printdeadlist __P((int, int, frentry_t *, char *, char *)); +static int state_matcharray __P((ipstate_t *, int *)); +static int printlivelist __P((friostat_t *, int, int, frentry_t *, + char *, char *)); +static void printdeadlist __P((friostat_t *, int, int, frentry_t *, + char *, char *)); +static void printside __P((char *, ipf_statistics_t *)); static void parse_ipportstr __P((const char *, i6addr_t *, int *)); static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); + ipfrstat_t **, ipf_authstat_t **, u_32_t *)); static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, - ipfrstat_t **, fr_authstat_t **, u_32_t *)); + ipfrstat_t **, ipf_authstat_t **, u_32_t *)); static ipstate_t *fetchstate __P((ipstate_t *, ipstate_t *)); #ifdef STATETOP static void topipstates __P((i6addr_t, i6addr_t, int, int, int, - int, int, int)); + int, int, int, int *)); static void sig_break __P((int)); static void sig_resize __P((int)); static char *getip __P((int, i6addr_t *)); @@ -167,7 +195,7 @@ static int sort_dstpt __P((const void *, const void *)); static void usage(name) -char *name; + char *name; { #ifdef USE_INET6 fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); @@ -186,20 +214,23 @@ char *name; int main(argc,argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - fr_authstat_t frauthst; - fr_authstat_t *frauthstp = &frauthst; + ipf_authstat_t frauthst; + ipf_authstat_t *frauthstp = &frauthst; friostat_t fio; friostat_t *fiop = &fio; ips_stat_t ipsst; ips_stat_t *ipsstp = &ipsst; ipfrstat_t ifrst; ipfrstat_t *ifrstp = &ifrst; - char *memf = NULL; - char *options, *kern = NULL; - int c, myoptind; + char *options; + char *kern = NULL; + char *memf = NULL; + int c; + int myoptind; + int *filter = NULL; int protocol = -1; /* -1 = wild card for any protocol */ int refreshtime = 1; /* default update time */ @@ -210,9 +241,9 @@ char *argv[]; u_32_t frf; #ifdef USE_INET6 - options = "6aACdfghIilnostvD:M:N:P:RS:T:"; + options = "6aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #else - options = "aACdfghIilnostvD:M:N:P:RS:T:"; + options = "aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #endif saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ @@ -324,6 +355,14 @@ char *argv[]; case 'l' : opts |= OPT_SHOWLIST; break; + case 'm' : + filter = parseipfexpr(optarg, NULL); + if (filter == NULL) { + fprintf(stderr, "Error parseing '%s'\n", + optarg); + exit(1); + } + break; case 'M' : break; case 'N' : @@ -334,6 +373,9 @@ char *argv[]; case 'o' : opts |= OPT_OUTQUE|OPT_SHOWLIST; break; + case 'O' : + state_fields = parsefields(statefields, optarg); + break; case 'P' : protocol = getproto(optarg); if (protocol == -1) { @@ -386,11 +428,12 @@ char *argv[]; ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); - } else + } else { ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); + } if (opts & OPT_IPSTATES) { - showipstates(ipsstp); + showipstates(ipsstp, filter); } else if (opts & OPT_SHOWLIST) { showlist(fiop); if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ @@ -402,7 +445,7 @@ char *argv[]; #ifdef STATETOP else if (opts & OPT_STATETOP) topipstates(saddr, daddr, sport, dport, protocol, - use_inet6 ? 6 : 4, refreshtime, topclosed); + use_inet6 ? 6 : 4, refreshtime, topclosed, filter); #endif else if (opts & OPT_AUTHSTATS) showauthstates(frauthstp); @@ -420,12 +463,12 @@ char *argv[]; * of ioctl's and copying directly from kernel memory. */ static void ipfstate_live(device, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *device; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; + char *device; + friostat_t **fiopp; + ips_stat_t **ipsstpp; + ipfrstat_t **ifrstpp; + ipf_authstat_t **frauthstpp; + u_32_t *frfp; { ipfobj_t ipfo; @@ -442,12 +485,12 @@ u_32_t *frfp; ipfo.ipfo_ptr = (void *)*fiopp; if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { - perror("ioctl(ipf:SIOCGETFS)"); + ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)"); exit(-1); } if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) - perror("ioctl(SIOCGETFF)"); + ipferror(ipf_fd, "ioctl(SIOCGETFF)"); } if ((opts & OPT_IPSTATES) != 0) { @@ -459,11 +502,11 @@ u_32_t *frfp; ipfo.ipfo_ptr = (void *)*ipsstpp; if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { - perror("ioctl(state:SIOCGETFS)"); + ipferror(state_fd, "ioctl(state:SIOCGETFS)"); exit(-1); } if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { - perror("ioctl(state:SIOCGETLG)"); + ipferror(state_fd, "ioctl(state:SIOCGETLG)"); exit(-1); } } @@ -474,9 +517,9 @@ u_32_t *frfp; ipfo.ipfo_type = IPFOBJ_FRAGSTAT; ipfo.ipfo_size = sizeof(ipfrstat_t); ipfo.ipfo_ptr = (void *)*ifrstpp; - + if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { - perror("ioctl(SIOCGFRST)"); + ipferror(ipf_fd, "ioctl(SIOCGFRST)"); exit(-1); } } @@ -488,11 +531,11 @@ u_32_t *frfp; bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_AUTHSTAT; - ipfo.ipfo_size = sizeof(fr_authstat_t); + ipfo.ipfo_size = sizeof(ipf_authstat_t); ipfo.ipfo_ptr = (void *)*frauthstpp; if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { - perror("ioctl(SIOCATHST)"); + ipferror(auth_fd, "ioctl(SIOCATHST)"); exit(-1); } } @@ -505,66 +548,64 @@ u_32_t *frfp; * just won't work any more. */ static void ipfstate_dead(kernel, fiopp, ipsstpp, ifrstpp, frauthstpp, frfp) -char *kernel; -friostat_t **fiopp; -ips_stat_t **ipsstpp; -ipfrstat_t **ifrstpp; -fr_authstat_t **frauthstpp; -u_32_t *frfp; + char *kernel; + friostat_t **fiopp; + ips_stat_t **ipsstpp; + ipfrstat_t **ifrstpp; + ipf_authstat_t **frauthstpp; + u_32_t *frfp; { - static fr_authstat_t frauthst, *frauthstp; + static ipf_authstat_t frauthst, *frauthstp; + static ipftq_t ipstcptab[IPF_TCP_NSTATES]; static ips_stat_t ipsst, *ipsstp; static ipfrstat_t ifrst, *ifrstp; static friostat_t fio, *fiop; - static ipftq_t ipssttab[IPF_TCP_NSTATES]; int temp; void *rules[2][2]; struct nlist deadlist[44] = { - { "fr_authstats" }, /* 0 */ - { "fae_list" }, - { "ipauth" }, - { "fr_authlist" }, - { "fr_authstart" }, - { "fr_authend" }, /* 5 */ - { "fr_authnext" }, - { "fr_auth" }, - { "fr_authused" }, - { "fr_authsize" }, - { "fr_defaultauthage" }, /* 10 */ - { "fr_authpkts" }, - { "fr_auth_lock" }, - { "frstats" }, - { "ips_stats" }, - { "ips_num" }, /* 15 */ - { "ips_wild" }, - { "ips_list" }, - { "ips_table" }, - { "fr_statemax" }, - { "fr_statesize" }, /* 20 */ - { "fr_state_doflush" }, - { "fr_state_lock" }, - { "ipfr_heads" }, - { "ipfr_nattab" }, - { "ipfr_stats" }, /* 25 */ - { "ipfr_inuse" }, - { "fr_ipfrttl" }, - { "fr_frag_lock" }, - { "ipfr_timer_id" }, - { "fr_nat_lock" }, /* 30 */ - { "ipfilter" }, - { "ipfilter6" }, - { "ipacct" }, - { "ipacct6" }, - { "ipl_frouteok" }, /* 35 */ - { "fr_running" }, - { "ipfgroups" }, - { "fr_active" }, - { "fr_pass" }, - { "fr_flags" }, /* 40 */ - { "ipstate_logging" }, - { "ips_tqtqb" }, - { NULL } + { "ipf_auth_stats", 0, 0, 0, 0 }, /* 0 */ + { "fae_list", 0, 0, 0, 0 }, + { "ipauth", 0, 0, 0, 0 }, + { "ipf_auth_list", 0, 0, 0, 0 }, + { "ipf_auth_start", 0, 0, 0, 0 }, + { "ipf_auth_end", 0, 0, 0, 0 }, /* 5 */ + { "ipf_auth_next", 0, 0, 0, 0 }, + { "ipf_auth", 0, 0, 0, 0 }, + { "ipf_auth_used", 0, 0, 0, 0 }, + { "ipf_auth_size", 0, 0, 0, 0 }, + { "ipf_auth_defaultage", 0, 0, 0, 0 }, /* 10 */ + { "ipf_auth_pkts", 0, 0, 0, 0 }, + { "ipf_auth_lock", 0, 0, 0, 0 }, + { "frstats", 0, 0, 0, 0 }, + { "ips_stats", 0, 0, 0, 0 }, + { "ips_num", 0, 0, 0, 0 }, /* 15 */ + { "ips_wild", 0, 0, 0, 0 }, + { "ips_list", 0, 0, 0, 0 }, + { "ips_table", 0, 0, 0, 0 }, + { "ipf_state_max", 0, 0, 0, 0 }, + { "ipf_state_size", 0, 0, 0, 0 }, /* 20 */ + { "ipf_state_doflush", 0, 0, 0, 0 }, + { "ipf_state_lock", 0, 0, 0, 0 }, + { "ipfr_heads", 0, 0, 0, 0 }, + { "ipfr_nattab", 0, 0, 0, 0 }, + { "ipfr_stats", 0, 0, 0, 0 }, /* 25 */ + { "ipfr_inuse", 0, 0, 0, 0 }, + { "ipf_ipfrttl", 0, 0, 0, 0 }, + { "ipf_frag_lock", 0, 0, 0, 0 }, + { "ipfr_timer_id", 0, 0, 0, 0 }, + { "ipf_nat_lock", 0, 0, 0, 0 }, /* 30 */ + { "ipf_rules", 0, 0, 0, 0 }, + { "ipf_acct", 0, 0, 0, 0 }, + { "ipl_frouteok", 0, 0, 0, 0 }, + { "ipf_running", 0, 0, 0, 0 }, + { "ipf_groups", 0, 0, 0, 0 }, /* 35 */ + { "ipf_active", 0, 0, 0, 0 }, + { "ipf_pass", 0, 0, 0, 0 }, + { "ipf_flags", 0, 0, 0, 0 }, + { "ipf_state_logging", 0, 0, 0, 0 }, + { "ips_tqtqb", 0, 0, 0, 0 }, /* 40 */ + { NULL, 0, 0, 0, 0 } }; @@ -618,23 +659,6 @@ u_32_t *frfp; fiop->f_fout[1] = rules[1][1]; /* - * Same for IPv6, except make them null if support for it is not - * being compiled in. - */ -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[32].n_value, sizeof(rules)); - fiop->f_fin6[0] = rules[0][0]; - fiop->f_fin6[1] = rules[0][1]; - fiop->f_fout6[0] = rules[1][0]; - fiop->f_fout6[1] = rules[1][1]; -#else - fiop->f_fin6[0] = NULL; - fiop->f_fin6[1] = NULL; - fiop->f_fout6[0] = NULL; - fiop->f_fout6[1] = NULL; -#endif - - /* * Now get accounting rules pointers. */ kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); @@ -643,32 +667,19 @@ u_32_t *frfp; fiop->f_acctout[0] = rules[1][0]; fiop->f_acctout[1] = rules[1][1]; -#ifdef USE_INET6 - kmemcpy((char *)&rules, (u_long)deadlist[34].n_value, sizeof(rules)); - fiop->f_acctin6[0] = rules[0][0]; - fiop->f_acctin6[1] = rules[0][1]; - fiop->f_acctout6[0] = rules[1][0]; - fiop->f_acctout6[1] = rules[1][1]; -#else - fiop->f_acctin6[0] = NULL; - fiop->f_acctin6[1] = NULL; - fiop->f_acctout6[0] = NULL; - fiop->f_acctout6[1] = NULL; -#endif - /* * A collection of "global" variables used inside the kernel which * are all collected in friostat_t via ioctl. */ - kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[35].n_value, + kmemcpy((char *)&fiop->f_froute, (u_long)deadlist[33].n_value, sizeof(fiop->f_froute)); - kmemcpy((char *)&fiop->f_running, (u_long)deadlist[36].n_value, + kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value, sizeof(fiop->f_running)); - kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[37].n_value, + kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value, sizeof(fiop->f_groups)); - kmemcpy((char *)&fiop->f_active, (u_long)deadlist[38].n_value, + kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value, sizeof(fiop->f_active)); - kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[39].n_value, + kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value, sizeof(fiop->f_defpass)); /* @@ -676,12 +687,12 @@ u_32_t *frfp; */ kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); - kmemcpy((char *)ipssttab, (u_long)deadlist[42].n_value, - sizeof(ipssttab)); + kmemcpy((char *)ipstcptab, (u_long)deadlist[40].n_value, + sizeof(ipstcptab)); ipsstp->iss_active = temp; ipsstp->iss_table = (void *)deadlist[18].n_value; ipsstp->iss_list = (void *)deadlist[17].n_value; - ipsstp->iss_tcptab = ipssttab; + ipsstp->iss_tcptab = ipstcptab; /* * Build up the authentiation information stats structure. @@ -708,65 +719,62 @@ u_32_t *frfp; } +static void printside(side, frs) + char *side; + ipf_statistics_t *frs; +{ + int i; + + PRINTF("%lu\t%s bad packets\n", frs->fr_bad, side); +#ifdef USE_INET6 + PRINTF("%lu\t%s IPv6 packets\n", frs->fr_ipv6, side); +#endif + PRINTF("%lu\t%s packets blocked\n", frs->fr_block, side); + PRINTF("%lu\t%s packets passed\n", frs->fr_pass, side); + PRINTF("%lu\t%s packets not matched\n", frs->fr_nom, side); + PRINTF("%lu\t%s packets counted\n", frs->fr_acct, side); + PRINTF("%lu\t%s packets short\n", frs->fr_short, side); + PRINTF("%lu\t%s packets logged and blocked\n", frs->fr_bpkl, side); + PRINTF("%lu\t%s packets logged and passed\n", frs->fr_ppkl, side); + PRINTF("%lu\t%s fragment state kept\n", frs->fr_nfr, side); + PRINTF("%lu\t%s fragment state lost\n", frs->fr_bnfr, side); + PRINTF("%lu\t%s packet state kept\n", frs->fr_ads, side); + PRINTF("%lu\t%s packet state lost\n", frs->fr_bads, side); + PRINTF("%lu\t%s invalid source\n", frs->fr_v4_badsrc, side); + PRINTF("%lu\t%s cache hits\n", frs->fr_chit, side); + PRINTF("%lu\t%s cache misses\n", frs->fr_cmiss, side); + PRINTF("%lu\t%s bad coalesces\n", frs->fr_badcoalesces, side); + PRINTF("%lu\t%s pullups succeeded\n", frs->fr_pull[0], side); + PRINTF("%lu\t%s pullups failed\n", frs->fr_pull[1], side); + PRINTF("%lu\t%s TCP checksum failures\n", frs->fr_tcpbad, side); + for (i = 0; i <= FRB_MAX_VALUE; i++) + PRINTF("%lu\t%s block reason %s\n", + frs->fr_blocked[i], side, blockreasons[i]); +} + + /* * Display the kernel stats for packets blocked and passed and other * associated running totals which are kept. */ static void showstats(fp, frf) -struct friostat *fp; -u_32_t frf; + struct friostat *fp; + u_32_t frf; { + printside("input", &fp->f_st[0]); + printside("output", &fp->f_st[1]); - PRINTF("bad packets:\t\tin %lu\tout %lu\n", - fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); -#ifdef USE_INET6 - PRINTF(" IPv6 packets:\t\tin %lu out %lu\n", - fp->f_st[0].fr_ipv6, fp->f_st[1].fr_ipv6); -#endif - PRINTF(" input packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[0].fr_block, fp->f_st[0].fr_pass, - fp->f_st[0].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[0].fr_acct, fp->f_st[0].fr_short); - PRINTF("output packets:\t\tblocked %lu passed %lu nomatch %lu", - fp->f_st[1].fr_block, fp->f_st[1].fr_pass, - fp->f_st[1].fr_nom); - PRINTF(" counted %lu short %lu\n", - fp->f_st[1].fr_acct, fp->f_st[1].fr_short); - PRINTF(" input packets logged:\tblocked %lu passed %lu\n", - fp->f_st[0].fr_bpkl, fp->f_st[0].fr_ppkl); - PRINTF("output packets logged:\tblocked %lu passed %lu\n", - fp->f_st[1].fr_bpkl, fp->f_st[1].fr_ppkl); - PRINTF(" packets logged:\tinput %lu output %lu\n", - fp->f_st[0].fr_pkl, fp->f_st[1].fr_pkl); - PRINTF(" log failures:\t\tinput %lu output %lu\n", - fp->f_st[0].fr_skip, fp->f_st[1].fr_skip); - PRINTF("fragment state(in):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[0].fr_nfr, fp->f_st[0].fr_bnfr, - fp->f_st[0].fr_cfr); - PRINTF("fragment state(out):\tkept %lu\tlost %lu\tnot fragmented %lu\n", - fp->f_st[1].fr_nfr, fp->f_st[1].fr_bnfr, - fp->f_st[0].fr_cfr); - PRINTF("packet state(in):\tkept %lu\tlost %lu\n", - fp->f_st[0].fr_ads, fp->f_st[0].fr_bads); - PRINTF("packet state(out):\tkept %lu\tlost %lu\n", - fp->f_st[1].fr_ads, fp->f_st[1].fr_bads); - PRINTF("ICMP replies:\t%lu\tTCP RSTs sent:\t%lu\n", - fp->f_st[0].fr_ret, fp->f_st[1].fr_ret); - PRINTF("Invalid source(in):\t%lu\n", fp->f_st[0].fr_badsrc); - PRINTF("Result cache hits(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_chit, fp->f_st[1].fr_chit); - PRINTF("IN Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[0].fr_pull[0], fp->f_st[0].fr_pull[1]); - PRINTF("OUT Pullups succeeded:\t%lu\tfailed:\t%lu\n", - fp->f_st[1].fr_pull[0], fp->f_st[1].fr_pull[1]); - PRINTF("Fastroute successes:\t%lu\tfailures:\t%lu\n", - fp->f_froute[0], fp->f_froute[1]); - PRINTF("TCP cksum fails(in):\t%lu\t(out):\t%lu\n", - fp->f_st[0].fr_tcpbad, fp->f_st[1].fr_tcpbad); - PRINTF("IPF Ticks:\t%lu\n", fp->f_ticks); + PRINTF("%lu\tpackets logged\n", fp->f_log_ok); + PRINTF("%lu\tlog failures\n", fp->f_log_fail); + PRINTF("%lu\tred-black no memory\n", fp->f_rb_no_mem); + PRINTF("%lu\tred-black node maximum\n", fp->f_rb_node_max); + PRINTF("%lu\tICMP replies sent\n", fp->f_st[0].fr_ret); + PRINTF("%lu\tTCP RSTs sent\n", fp->f_st[1].fr_ret); + PRINTF("%lu\tfastroute successes\n", fp->f_froute[0]); + PRINTF("%lu\tfastroute failures\n", fp->f_froute[1]); + PRINTF("%u\tIPF Ticks\n", fp->f_ticks); - PRINTF("Packet log flags set: (%#x)\n", frf); + PRINTF("%x\tPacket log flags set:\n", frf); if (frf & FF_LOGPASS) PRINTF("\tpackets passed through filter\n"); if (frf & FF_LOGBLOCK) @@ -781,30 +789,27 @@ u_32_t frf; /* * Print out a list of rules from the kernel, starting at the one passed. */ -static void printlivelist(out, set, fp, group, comment) -int out, set; -frentry_t *fp; -char *group, *comment; +static int +printlivelist(fiop, out, set, fp, group, comment) + struct friostat *fiop; + int out, set; + frentry_t *fp; + char *group, *comment; { struct frentry fb; ipfruleiter_t rule; frentry_t zero; frgroup_t *g; ipfobj_t obj; - int n; + int rules; + int num; - if (use_inet6 == 1) - fb.fr_v = 6; - else - fb.fr_v = 4; - fb.fr_next = fp; - n = 0; + rules = 0; rule.iri_inout = out; rule.iri_active = set; rule.iri_rule = &fb; rule.iri_nrules = 1; - rule.iri_v = use_inet6 ? 6 : 4; if (group != NULL) strncpy(rule.iri_group, group, FR_GROUPLEN); else @@ -818,49 +823,65 @@ char *group, *comment; obj.ipfo_size = sizeof(rule); obj.ipfo_ptr = &rule; - do { + while (rule.iri_rule != NULL) { u_long array[1000]; memset(array, 0xff, sizeof(array)); fp = (frentry_t *)array; rule.iri_rule = fp; if (ioctl(ipf_fd, SIOCIPFITER, &obj) == -1) { - perror("ioctl(SIOCIPFITER)"); - n = IPFGENITER_IPF; - ioctl(ipf_fd, SIOCIPFDELTOK, &n); - return; + ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); + num = IPFGENITER_IPF; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); + return rules; } if (bcmp(fp, &zero, sizeof(zero)) == 0) break; + if (rule.iri_rule == NULL) + break; +#ifdef USE_INET6 + if (use_inet6 != 0) { + if (fp->fr_family != 0 && fp->fr_family != AF_INET6) + continue; + } else +#endif + { + if (fp->fr_family != 0 && fp->fr_family != AF_INET) + continue; + } if (fp->fr_data != NULL) - fp->fr_data = (char *)fp + sizeof(*fp); + fp->fr_data = (char *)fp + fp->fr_size; - n++; + rules++; - if (opts & (OPT_HITS|OPT_VERBOSE)) + if (opts & (OPT_HITS|OPT_DEBUG)) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_hits); + PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits); #else PRINTF("%lu ", fp->fr_hits); #endif - if (opts & (OPT_ACCNT|OPT_VERBOSE)) + if (opts & (OPT_ACCNT|OPT_DEBUG)) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fp->fr_bytes); + PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes); #else PRINTF("%lu ", fp->fr_bytes); #endif if (opts & OPT_SHOWLINENO) - PRINTF("@%d ", n); + PRINTF("@%d ", rules); + + if (fp->fr_die != 0) + fp->fr_die -= fiop->f_ticks; printfr(fp, ioctl); if (opts & OPT_DEBUG) { - binprint(fp, sizeof(*fp)); + binprint(fp, fp->fr_size); if (fp->fr_data != NULL && fp->fr_dsize > 0) binprint(fp->fr_data, fp->fr_dsize); } - if (fp->fr_grhead[0] != '\0') { + if (fp->fr_grhead != -1) { for (g = grtop; g != NULL; g = g->fg_next) { - if (!strncmp(fp->fr_grhead, g->fg_name, + if (!strncmp(fp->fr_names + fp->fr_grhead, + g->fg_name, FR_GROUPLEN)) break; } @@ -868,7 +889,8 @@ char *group, *comment; g = calloc(1, sizeof(*g)); if (g != NULL) { - strncpy(g->fg_name, fp->fr_grhead, + strncpy(g->fg_name, + fp->fr_names + fp->fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; @@ -881,29 +903,23 @@ char *group, *comment; } } if (fp->fr_type == FR_T_CALLFUNC) { - printlivelist(out, set, fp->fr_data, group, - "# callfunc: "); + rules += printlivelist(fiop, out, set, fp->fr_data, + group, "# callfunc: "); } - } while (fp->fr_next != NULL); + } - n = IPFGENITER_IPF; - ioctl(ipf_fd, SIOCIPFDELTOK, &n); + num = IPFGENITER_IPF; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); - if (group == NULL) { - while ((g = grtop) != NULL) { - printf("# Group %s\n", g->fg_name); - printlivelist(out, set, NULL, g->fg_name, comment); - grtop = g->fg_next; - free(g); - } - } + return rules; } -static void printdeadlist(out, set, fp, group, comment) -int out, set; -frentry_t *fp; -char *group, *comment; +static void printdeadlist(fiop, out, set, fp, group, comment) + friostat_t *fiop; + int out, set; + frentry_t *fp; + char *group, *comment; { frgroup_t *grtop, *grtail, *g; struct frentry fb; @@ -916,13 +932,20 @@ char *group, *comment; grtop = NULL; grtail = NULL; - do { - fp = fb.fr_next; + for (n = 1; fp; fp = fb.fr_next, n++) { if (kmemcpy((char *)&fb, (u_long)fb.fr_next, - sizeof(fb)) == -1) { + fb.fr_size) == -1) { perror("kmemcpy"); return; } + fp = &fb; + if (use_inet6 != 0) { + if (fp->fr_family != 0 && fp->fr_family != 6) + continue; + } else { + if (fp->fr_family != 0 && fp->fr_family != 4) + continue; + } data = NULL; type = fb.fr_type & ~FR_T_BUILTIN; @@ -939,17 +962,15 @@ char *group, *comment; } } - n++; - - if (opts & (OPT_HITS|OPT_VERBOSE)) + if (opts & OPT_HITS) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fb.fr_hits); + PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits); #else PRINTF("%lu ", fb.fr_hits); #endif - if (opts & (OPT_ACCNT|OPT_VERBOSE)) + if (opts & OPT_ACCNT) #ifdef USE_QUAD_T - PRINTF("%qu ", (unsigned long long) fb.fr_bytes); + PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes); #else PRINTF("%lu ", fb.fr_bytes); #endif @@ -958,17 +979,17 @@ char *group, *comment; printfr(fp, ioctl); if (opts & OPT_DEBUG) { - binprint(fp, sizeof(*fp)); + binprint(fp, fp->fr_size); if (fb.fr_data != NULL && fb.fr_dsize > 0) binprint(fb.fr_data, fb.fr_dsize); } if (data != NULL) free(data); - if (fb.fr_grhead[0] != '\0') { + if (fb.fr_grhead != -1) { g = calloc(1, sizeof(*g)); if (g != NULL) { - strncpy(g->fg_name, fb.fr_grhead, + strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; @@ -980,13 +1001,13 @@ char *group, *comment; } } if (type == FR_T_CALLFUNC) { - printdeadlist(out, set, fb.fr_data, group, + printdeadlist(fiop, out, set, fb.fr_data, group, "# callfunc: "); } - } while (fb.fr_next != NULL); + } while ((g = grtop) != NULL) { - printdeadlist(out, set, NULL, g->fg_name, comment); + printdeadlist(fiop, out, set, NULL, g->fg_name, comment); grtop = g->fg_next; free(g); } @@ -997,7 +1018,7 @@ char *group, *comment; * the base from which to get the pointers. */ static void showlist(fiop) -struct friostat *fiop; + struct friostat *fiop; { struct frentry *fp = NULL; int i, set; @@ -1006,15 +1027,6 @@ struct friostat *fiop; if (opts & OPT_INACTIVE) set = 1 - set; if (opts & OPT_ACCNT) { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_ACOUT; - fp = (struct frentry *)fiop->f_acctout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_ACIN; - fp = (struct frentry *)fiop->f_acctin6[set]; - } else -#endif if (opts & OPT_OUTQUE) { i = F_ACOUT; fp = (struct frentry *)fiop->f_acctout[set]; @@ -1026,15 +1038,6 @@ struct friostat *fiop; return; } } else { -#ifdef USE_INET6 - if ((use_inet6) && (opts & OPT_OUTQUE)) { - i = F_OUT; - fp = (struct frentry *)fiop->f_fout6[set]; - } else if ((use_inet6) && (opts & OPT_INQUE)) { - i = F_IN; - fp = (struct frentry *)fiop->f_fin6[set]; - } else -#endif if (opts & OPT_OUTQUE) { i = F_OUT; fp = (struct frentry *)fiop->f_fout[set]; @@ -1049,139 +1052,243 @@ struct friostat *fiop; if (opts & OPT_DEBUG) PRINTF("fp %p set %d\n", fp, set); - if (!fp) { - FPRINTF(stderr, "empty list for %s%s\n", - (opts & OPT_INACTIVE) ? "inactive " : "", filters[i]); - return; + + if (live_kernel == 1) { + int printed; + + printed = printlivelist(fiop, i, set, fp, NULL, NULL); + if (printed == 0) { + FPRINTF(stderr, "# empty list for %s%s\n", + (opts & OPT_INACTIVE) ? "inactive " : "", + filters[i]); + } + } else { + if (!fp) { + FPRINTF(stderr, "# empty list for %s%s\n", + (opts & OPT_INACTIVE) ? "inactive " : "", + filters[i]); + } else { + printdeadlist(fiop, i, set, fp, NULL, NULL); + } } - if (live_kernel == 1) - printlivelist(i, set, fp, NULL, NULL); - else - printdeadlist(i, set, fp, NULL, NULL); } /* * Display ipfilter stateful filtering information */ -static void showipstates(ipsp) -ips_stat_t *ipsp; +static void showipstates(ipsp, filter) + ips_stat_t *ipsp; + int *filter; { - u_long minlen, maxlen, totallen, *buckets; - ipftable_t table; - ipfobj_t obj; - int i, sz; + ipstate_t *is; + int i; /* * If a list of states hasn't been asked for, only print out stats */ if (!(opts & OPT_SHOWLIST)) { + showstatestats(ipsp); + return; + } - sz = sizeof(*buckets) * ipsp->iss_statesize; - buckets = (u_long *)malloc(sz); + if ((state_fields != NULL) && (nohdrfields == 0)) { + for (i = 0; state_fields[i].w_value != 0; i++) { + printfieldhdr(statefields, state_fields + i); + if (state_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_type = IPFOBJ_GTABLE; - obj.ipfo_size = sizeof(table); - obj.ipfo_ptr = &table; + /* + * Print out all the state information currently held in the kernel. + */ + for (is = ipsp->iss_list; is != NULL; ) { + ipstate_t ips; - table.ita_type = IPFTABLE_BUCKETS; - table.ita_table = buckets; + is = fetchstate(is, &ips); - if (live_kernel == 1) { - if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { - free(buckets); - return; + if (is == NULL) + break; + + is = ips.is_next; + if ((filter != NULL) && + (state_matcharray(&ips, filter) == 0)) { + continue; + } + if (state_fields != NULL) { + for (i = 0; state_fields[i].w_value != 0; i++) { + printstatefield(&ips, state_fields[i].w_value); + if (state_fields[i + 1].w_value != 0) + printf("\t"); } + printf("\n"); } else { - if (kmemcpy((char *)buckets, - (u_long)ipsp->iss_bucketlen, sz)) { - free(buckets); - return; - } + printstate(&ips, opts, ipsp->iss_ticks); } + } +} - PRINTF("IP states added:\n\t%lu TCP\n\t%lu UDP\n\t%lu ICMP\n", - ipsp->iss_tcp, ipsp->iss_udp, ipsp->iss_icmp); - PRINTF("\t%lu hits\n\t%lu misses\n", ipsp->iss_hits, - ipsp->iss_miss); - PRINTF("\t%lu bucket full\n", ipsp->iss_bucketfull); - PRINTF("\t%lu maximum rule references\n", ipsp->iss_maxref); - PRINTF("\t%lu maximum\n\t%lu no memory\n\t%lu bkts in use\n", - ipsp->iss_max, ipsp->iss_nomem, ipsp->iss_inuse); - PRINTF("\t%lu active\n\t%lu expired\n\t%lu closed\n", - ipsp->iss_active, ipsp->iss_expire, ipsp->iss_fin); - - PRINTF("State logging %sabled\n", - state_logging ? "en" : "dis"); - PRINTF("\nState table bucket statistics:\n"); - PRINTF("\t%lu in use\t\n", ipsp->iss_inuse); - PRINTF("\t%u%% hash efficiency\n", ipsp->iss_active ? - (u_int)(ipsp->iss_inuse * 100 / ipsp->iss_active) : 0); +static void showstatestats(ipsp) + ips_stat_t *ipsp; +{ + int minlen, maxlen, totallen; + ipftable_t table; + u_int *buckets; + ipfobj_t obj; + int i, sz; - minlen = ipsp->iss_inuse; - totallen = 0; - maxlen = 0; + /* + * If a list of states hasn't been asked for, only print out stats + */ - for (i = 0; i < ipsp->iss_statesize; i++) { - if (buckets[i] > maxlen) - maxlen = buckets[i]; - if (buckets[i] < minlen) - minlen = buckets[i]; - totallen += buckets[i]; - } + sz = sizeof(*buckets) * ipsp->iss_state_size; + buckets = (u_int *)malloc(sz); - PRINTF("\t%2.2f%% bucket usage\n\t%lu minimal length\n", - ((float)ipsp->iss_inuse / ipsp->iss_statesize) * 100.0, - minlen); - PRINTF("\t%lu maximal length\n\t%.3f average length\n", - maxlen, - ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : - 0.0); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_GTABLE; + obj.ipfo_size = sizeof(table); + obj.ipfo_ptr = &table; -#define ENTRIES_PER_LINE 5 + table.ita_type = IPFTABLE_BUCKETS; + table.ita_table = buckets; - if (opts & OPT_VERBOSE) { - PRINTF("\nCurrent bucket sizes :\n"); - for (i = 0; i < ipsp->iss_statesize; i++) { - if ((i % ENTRIES_PER_LINE) == 0) - PRINTF("\t"); - PRINTF("%4d -> %4lu", i, buckets[i]); - if ((i % ENTRIES_PER_LINE) == - (ENTRIES_PER_LINE - 1)) - PRINTF("\n"); - else - PRINTF(" "); - } - PRINTF("\n"); + if (live_kernel == 1) { + if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { + free(buckets); + return; } - PRINTF("\n"); + } else { + if (kmemcpy((char *)buckets, + (u_long)ipsp->iss_bucketlen, sz)) { + free(buckets); + return; + } + } - free(buckets); + PRINTF("%u\tactive state table entries\n",ipsp->iss_active); + PRINTF("%lu\tadd bad\n", ipsp->iss_add_bad); + PRINTF("%lu\tadd duplicate\n", ipsp->iss_add_dup); + PRINTF("%lu\tadd locked\n", ipsp->iss_add_locked); + PRINTF("%lu\tadd oow\n", ipsp->iss_add_oow); + PRINTF("%lu\tbucket full\n", ipsp->iss_bucket_full); + PRINTF("%lu\tcheck bad\n", ipsp->iss_check_bad); + PRINTF("%lu\tcheck miss\n", ipsp->iss_check_miss); + PRINTF("%lu\tcheck nattag\n", ipsp->iss_check_nattag); + PRINTF("%lu\tclone nomem\n", ipsp->iss_clone_nomem); + PRINTF("%lu\tcheck notag\n", ipsp->iss_check_notag); + PRINTF("%lu\tcheck success\n", ipsp->iss_hits); + PRINTF("%lu\tcloned\n", ipsp->iss_cloned); + PRINTF("%lu\texpired\n", ipsp->iss_expire); + PRINTF("%lu\tflush all\n", ipsp->iss_flush_all); + PRINTF("%lu\tflush closing\n", ipsp->iss_flush_closing); + PRINTF("%lu\tflush queue\n", ipsp->iss_flush_queue); + PRINTF("%lu\tflush state\n", ipsp->iss_flush_state); + PRINTF("%lu\tflush timeout\n", ipsp->iss_flush_timeout); + PRINTF("%u\thash buckets in use\n", ipsp->iss_inuse); + PRINTF("%lu\tICMP bad\n", ipsp->iss_icmp_bad); + PRINTF("%lu\tICMP banned\n", ipsp->iss_icmp_banned); + PRINTF("%lu\tICMP errors\n", ipsp->iss_icmp_icmperr); + PRINTF("%lu\tICMP head block\n", ipsp->iss_icmp_headblock); + PRINTF("%lu\tICMP hits\n", ipsp->iss_icmp_hits); + PRINTF("%lu\tICMP not query\n", ipsp->iss_icmp_notquery); + PRINTF("%lu\tICMP short\n", ipsp->iss_icmp_short); + PRINTF("%lu\tICMP too many\n", ipsp->iss_icmp_toomany); + PRINTF("%lu\tICMPv6 errors\n", ipsp->iss_icmp6_icmperr); + PRINTF("%lu\tICMPv6 miss\n", ipsp->iss_icmp6_miss); + PRINTF("%lu\tICMPv6 not info\n", ipsp->iss_icmp6_notinfo); + PRINTF("%lu\tICMPv6 not query\n", ipsp->iss_icmp6_notquery); + PRINTF("%lu\tlog fail\n", ipsp->iss_log_fail); + PRINTF("%lu\tlog ok\n", ipsp->iss_log_ok); + PRINTF("%lu\tlookup interface mismatch\n", ipsp->iss_lookup_badifp); + PRINTF("%lu\tlookup mask mismatch\n", ipsp->iss_miss_mask); + PRINTF("%lu\tlookup port mismatch\n", ipsp->iss_lookup_badport); + PRINTF("%lu\tlookup miss\n", ipsp->iss_lookup_miss); + PRINTF("%lu\tmaximum rule references\n", ipsp->iss_max_ref); + PRINTF("%lu\tmaximum hosts per rule\n", ipsp->iss_max_track); + PRINTF("%lu\tno memory\n", ipsp->iss_nomem); + PRINTF("%lu\tout of window\n", ipsp->iss_oow); + PRINTF("%lu\torphans\n", ipsp->iss_orphan); + PRINTF("%lu\tscan block\n", ipsp->iss_scan_block); + PRINTF("%lu\tstate table maximum reached\n", ipsp->iss_max); + PRINTF("%lu\tTCP closing\n", ipsp->iss_tcp_closing); + PRINTF("%lu\tTCP OOW\n", ipsp->iss_tcp_oow); + PRINTF("%lu\tTCP RST add\n", ipsp->iss_tcp_rstadd); + PRINTF("%lu\tTCP too small\n", ipsp->iss_tcp_toosmall); + PRINTF("%lu\tTCP bad options\n", ipsp->iss_tcp_badopt); + PRINTF("%lu\tTCP removed\n", ipsp->iss_fin); + PRINTF("%lu\tTCP FSM\n", ipsp->iss_tcp_fsm); + PRINTF("%lu\tTCP strict\n", ipsp->iss_tcp_strict); + PRINTF("%lu\tTCP wild\n", ipsp->iss_wild); + PRINTF("%lu\tMicrosoft Windows SACK\n", ipsp->iss_winsack); - if (live_kernel == 1) { - showtqtable_live(state_fd); - } else { - printtqtable(ipsp->iss_tcptab); + PRINTF("State logging %sabled\n", state_logging ? "en" : "dis"); + + PRINTF("IP states added:\n"); + for (i = 0; i < 256; i++) { + if (ipsp->iss_proto[i] != 0) { + struct protoent *proto; + + proto = getprotobynumber(i); + PRINTF("%lu", ipsp->iss_proto[i]); + if (proto != NULL) + PRINTF("\t%s\n", proto->p_name); + else + PRINTF("\t%d\n", i); } + } - return; + PRINTF("\nState table bucket statistics:\n"); + PRINTF("%u\tin use\n", ipsp->iss_inuse); + + minlen = ipsp->iss_max; + totallen = 0; + maxlen = 0; + for (i = 0; i < ipsp->iss_state_size; i++) { + if (buckets[i] > maxlen) + maxlen = buckets[i]; + if (buckets[i] < minlen) + minlen = buckets[i]; + totallen += buckets[i]; } - /* - * Print out all the state information currently held in the kernel. - */ - while (ipsp->iss_list != NULL) { - ipstate_t ips; + PRINTF("%d\thash efficiency\n", + totallen ? ipsp->iss_inuse * 100 / totallen : 0); + PRINTF("%2.2f%%\tbucket usage\n%u\tminimal length\n", + ((float)ipsp->iss_inuse / ipsp->iss_state_size) * 100.0, + minlen); + PRINTF("%u\tmaximal length\n%.3f\taverage length\n", + maxlen, + ipsp->iss_inuse ? (float) totallen/ ipsp->iss_inuse : + 0.0); - ipsp->iss_list = fetchstate(ipsp->iss_list, &ips); +#define ENTRIES_PER_LINE 5 - if (ipsp->iss_list != NULL) { - ipsp->iss_list = ips.is_next; - printstate(&ips, opts, ipsp->iss_ticks); + if (opts & OPT_VERBOSE) { + PRINTF("\nCurrent bucket sizes :\n"); + for (i = 0; i < ipsp->iss_state_size; i++) { + if ((i % ENTRIES_PER_LINE) == 0) + PRINTF("\t"); + PRINTF("%4d -> %4u", i, buckets[i]); + if ((i % ENTRIES_PER_LINE) == + (ENTRIES_PER_LINE - 1)) + PRINTF("\n"); + else + PRINTF(" "); } + PRINTF("\n"); + } + PRINTF("\n"); + + free(buckets); + + if (live_kernel == 1) { + showtqtable_live(state_fd); + } else { + printtqtable(ipsp->iss_tcptab); } } @@ -1190,21 +1297,23 @@ ips_stat_t *ipsp; static int handle_resize = 0, handle_break = 0; static void topipstates(saddr, daddr, sport, dport, protocol, ver, - refreshtime, topclosed) -i6addr_t saddr; -i6addr_t daddr; -int sport; -int dport; -int protocol; -int ver; -int refreshtime; -int topclosed; + refreshtime, topclosed, filter) + i6addr_t saddr; + i6addr_t daddr; + int sport; + int dport; + int protocol; + int ver; + int refreshtime; + int topclosed; + int *filter; { char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; int i, j, winy, tsentry, maxx, maxy, redraw = 0, ret = 0; int len, srclen, dstlen, forward = 1, c = 0; ips_stat_t ipsst, *ipsstp = &ipsst; + int token_type = IPFGENITER_STATE; statetop_t *tstable = NULL, *tp; const char *errstr = ""; ipstate_t ips; @@ -1267,6 +1376,10 @@ int topclosed; if (ips.is_v != ver) continue; + if ((filter != NULL) && + (state_matcharray(&ips, filter) == 0)) + continue; + /* check v4 src/dest addresses */ if (ips.is_v == 4) { if ((saddr.in4.s_addr != INADDR_ANY && @@ -1348,6 +1461,7 @@ int topclosed; } } + (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); /* sort the array */ if (tsentry != -1) { @@ -1485,14 +1599,14 @@ int topclosed; printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", str1, str2, str3, str4); - /* + /* * For an IPv4 IP address we need at most 15 characters, * 4 tuples of 3 digits, separated by 3 dots. Enforce this * length, so the colums do not change positions based * on the size of the IP address. This length makes the - * output fit in a 80 column terminal. + * output fit in a 80 column terminal. * We are lacking a good solution for IPv6 addresses (that - * can be longer that 15 characters), so we do not enforce + * can be longer that 15 characters), so we do not enforce * a maximum on the IP field size. */ if (srclen < 15) @@ -1629,8 +1743,8 @@ out: * Show fragment cache information that's held in the kernel. */ static void showfrstates(ifsp, ticks) -ipfrstat_t *ifsp; -u_long ticks; + ipfrstat_t *ifsp; + u_long ticks; { struct ipfr *ipfrtab[IPFT_SIZE], ifr; int i; @@ -1638,13 +1752,13 @@ u_long ticks; /* * print out the numeric statistics */ - PRINTF("IP fragment states:\n\t%lu new\n\t%lu expired\n\t%lu hits\n", + PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); - PRINTF("\t%lu retrans\n\t%lu too short\n", + PRINTF("%lu\tretrans\n%lu\ttoo short\n", ifsp->ifs_retrans0, ifsp->ifs_short); - PRINTF("\t%lu no memory\n\t%lu already exist\n", + PRINTF("%lu\tno memory\n%lu\talready exist\n", ifsp->ifs_nomem, ifsp->ifs_exists); - PRINTF("\t%lu inuse\n", ifsp->ifs_inuse); + PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); PRINTF("\n"); if (live_kernel == 0) { @@ -1664,7 +1778,7 @@ u_long ticks; break; ifr.ipfr_ttl -= ticks; printfraginfo("", &ifr); - } while (1); + } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { @@ -1693,7 +1807,7 @@ u_long ticks; break; ifr.ipfr_ttl -= ticks; printfraginfo("NAT: ", &ifr); - } while (1); + } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { @@ -1711,7 +1825,7 @@ u_long ticks; * Show stats on how auth within IPFilter has been used */ static void showauthstates(asp) -fr_authstat_t *asp; + ipf_authstat_t *asp; { frauthent_t *frap, fra; ipfgeniter_t auth; @@ -1727,7 +1841,7 @@ fr_authstat_t *asp; auth.igi_data = &fra; #ifdef USE_QUAD_T - printf("Authorisation hits: %qu\tmisses %qu\n", + printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n", (unsigned long long) asp->fas_hits, (unsigned long long) asp->fas_miss); #else @@ -1762,7 +1876,7 @@ fr_authstat_t *asp; * authentication, separately. */ static void showgroups(fiop) -struct friostat *fiop; + struct friostat *fiop; { static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; @@ -1790,10 +1904,11 @@ struct friostat *fiop; } } + static void parse_ipportstr(argument, ip, port) -const char *argument; -i6addr_t *ip; -int *port; + const char *argument; + i6addr_t *ip; + int *port; { char *s, *comma; int ok = 0; @@ -1845,20 +1960,20 @@ int *port; #ifdef STATETOP static void sig_resize(s) -int s; + int s; { handle_resize = 1; } static void sig_break(s) -int s; + int s; { handle_break = 1; } static char *getip(v, addr) -int v; -i6addr_t *addr; + int v; + i6addr_t *addr; { #ifdef USE_INET6 static char hostbuf[MAXHOSTNAMELEN+1]; @@ -1878,7 +1993,7 @@ i6addr_t *addr; static char *ttl_to_string(ttl) -long int ttl; + long int ttl; { static char ttlbuf[STSTRSIZE]; int hours, minutes, seconds; @@ -1900,8 +2015,8 @@ long int ttl; static int sort_pkts(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; @@ -1916,8 +2031,8 @@ const void *b; static int sort_bytes(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1931,8 +2046,8 @@ const void *b; static int sort_p(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1946,8 +2061,8 @@ const void *b; static int sort_ttl(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1960,8 +2075,8 @@ const void *b; } static int sort_srcip(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -1986,8 +2101,8 @@ const void *b; } static int sort_srcpt(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -2000,8 +2115,8 @@ const void *b; } static int sort_dstip(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -2026,8 +2141,8 @@ const void *b; } static int sort_dstpt(a, b) -const void *a; -const void *b; + const void *a; + const void *b; { register const statetop_t *ap = a; register const statetop_t *bp = b; @@ -2043,9 +2158,8 @@ const void *b; ipstate_t *fetchstate(src, dst) -ipstate_t *src, *dst; + ipstate_t *src, *dst; { - int i; if (live_kernel == 1) { ipfgeniter_t state; @@ -2063,8 +2177,8 @@ ipstate_t *src, *dst; if (ioctl(state_fd, SIOCGENITER, &obj) != 0) return NULL; if (dst->is_next == NULL) { - i = IPFGENITER_STATE; - ioctl(state_fd, SIOCIPFDELTOK, &i); + int n = IPFGENITER_STATE; + (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n); } } else { if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) @@ -2075,8 +2189,8 @@ ipstate_t *src, *dst; static int fetchfrag(fd, type, frp) -int fd, type; -ipfr_t *frp; + int fd, type; + ipfr_t *frp; { ipfgeniter_t frag; ipfobj_t obj; @@ -2096,8 +2210,155 @@ ipfr_t *frp; } +static int state_matcharray(stp, array) + ipstate_t *stp; + int *array; +{ + int i, n, *x, rv, p; + ipfexp_t *e; + + rv = 0; + + for (n = array[0], x = array + 1; n > 0; x += e->ipfe_size) { + e = (ipfexp_t *)x; + if (e->ipfe_cmd == IPF_EXP_END) + break; + n -= e->ipfe_size; + + rv = 0; + /* + * The upper 16 bits currently store the protocol value. + * This is currently used with TCP and UDP port compares and + * allows "tcp.port = 80" without requiring an explicit + " "ip.pr = tcp" first. + */ + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != stp->is_p)) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_p == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_DSTADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (stp->is_v != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((stp->is_saddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((stp->is_daddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_src, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_dst, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (stp->is_v != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&stp->is_src, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&stp->is_dst, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_sport == e->ipfe_arg0[i]) || + (stp->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_sport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_dport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IDLE_GT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_die < e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_TCP_STATE : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (stp->is_state[0] == e->ipfe_arg0[i]) || + (stp->is_state[1] == e->ipfe_arg0[i]); + } + break; + } + rv ^= e->ipfe_not; + + if (rv == 0) + break; + } + + return rv; +} + + static void showtqtable_live(fd) -int fd; + int fd; { ipftq_t table[IPF_TCP_NSTATES]; ipfobj_t obj; diff --git a/contrib/ipfilter/tools/ipfsyncd.c b/contrib/ipfilter/tools/ipfsyncd.c new file mode 100644 index 000000000000..d4671e409d63 --- /dev/null +++ b/contrib/ipfilter/tools/ipfsyncd.c @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +#if !defined(lint) +static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ipfsyncd.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $"; +#endif +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/sockio.h> +#include <sys/errno.h> + +#include <netinet/in.h> +#include <net/if.h> + +#include <arpa/inet.h> + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <syslog.h> +#include <signal.h> + +#include "ipf.h" +#include "opts.h" + + +#define R_IO_ERROR -1 +#define R_OKAY 0 +#define R_MORE 1 +#define R_SKIP 2 +#if defined(sun) && !defined(SOLARIS2) +# define STRERROR(x) sys_errlist[x] +extern char *sys_errlist[]; +#else +# define STRERROR(x) strerror(x) +#endif + + +int main __P((int, char *[])); +void usage __P((char *)); +void printsynchdr __P((synchdr_t *)); +void printtable __P((int)); +void printsmcproto __P((char *)); +void printcommand __P((int)); +int do_kbuff __P((int, char *, int *)); +int do_packet __P((int, char *)); +int buildsocket __P((char *, struct sockaddr_in *)); +void do_io __P((void)); +void handleterm __P((int)); + +int terminate = 0; +int igmpfd = -1; +int nfd = -1; +int lfd = -1; +int opts = 0; + +void +usage(progname) + char *progname; +{ + fprintf(stderr, + "Usage: %s [-d] [-p port] [-i address] -I <interface>\n", + progname); +} + +void +handleterm(sig) + int sig; +{ + terminate = sig; +} + + +/* should be large enough to hold header + any datatype */ +#define BUFFERLEN 1400 + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct sockaddr_in sin; + char *interface; + char *progname; + int opt, tries; + + progname = strrchr(argv[0], '/'); + if (progname) { + progname++; + } else { + progname = argv[0]; + } + + opts = 0; + tries = 0; + interface = NULL; + + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(0xaf6c); + sin.sin_addr.s_addr = htonl(INADDR_UNSPEC_GROUP | 0x697066); + + while ((opt = getopt(argc, argv, "di:I:p:")) != -1) + switch (opt) + { + case 'd' : + debuglevel++; + break; + case 'I' : + interface = optarg; + break; + case 'i' : + sin.sin_addr.s_addr = inet_addr(optarg); + break; + case 'p' : + sin.sin_port = htons(atoi(optarg)); + break; + } + + if (interface == NULL) { + usage(progname); + exit(1); + } + + if (!debuglevel) { + +#if BSD >= 199306 + daemon(0, 0); +#else + int fd = open("/dev/null", O_RDWR); + + switch (fork()) + { + case 0 : + break; + + case -1 : + fprintf(stderr, "%s: fork() failed: %s\n", + argv[0], STRERROR(errno)); + exit(1); + /* NOTREACHED */ + + default : + exit(0); + /* NOTREACHED */ + } + + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + + setsid(); +#endif + } + + signal(SIGHUP, handleterm); + signal(SIGINT, handleterm); + signal(SIGTERM, handleterm); + + openlog(progname, LOG_PID, LOG_SECURITY); + + while (!terminate) { + if (lfd != -1) { + close(lfd); + lfd = -1; + } + if (nfd != -1) { + close(nfd); + nfd = -1; + } + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + + if (buildsocket(interface, &sin) == -1) + goto tryagain; + + lfd = open(IPSYNC_NAME, O_RDWR); + if (lfd == -1) { + syslog(LOG_ERR, "open(%s):%m", IPSYNC_NAME); + debug(1, "open(%s): %s\n", IPSYNC_NAME, + STRERROR(errno)); + goto tryagain; + } + + tries = -1; + do_io(); +tryagain: + tries++; + syslog(LOG_INFO, "retry in %d seconds", 1 << tries); + debug(1, "wait %d seconds\n", 1 << tries); + sleep(1 << tries); + } + + + /* terminate */ + if (lfd != -1) + close(lfd); + if (nfd != -1) + close(nfd); + + syslog(LOG_ERR, "signal %d received, exiting...", terminate); + debug(1, "signal %d received, exiting...", terminate); + + exit(1); +} + + +void +do_io() +{ + char nbuff[BUFFERLEN]; + char buff[BUFFERLEN]; + fd_set mrd, rd; + int maxfd; + int inbuf; + int n1; + int left; + + FD_ZERO(&mrd); + FD_SET(lfd, &mrd); + FD_SET(nfd, &mrd); + maxfd = nfd; + if (lfd > maxfd) + maxfd = lfd; + debug(2, "nfd %d lfd %d maxfd %d\n", nfd, lfd, maxfd); + + inbuf = 0; + /* + * A threaded approach to this loop would have one thread + * work on reading lfd (only) all the time and another thread + * working on reading nfd all the time. + */ + while (!terminate) { + int n; + + rd = mrd; + + n = select(maxfd + 1, &rd, NULL, NULL, NULL); + if (n < 0) { + switch (errno) + { + case EINTR : + continue; + default : + syslog(LOG_ERR, "select error: %m"); + debug(1, "select error: %s\n", STRERROR(errno)); + return; + } + } + + if (FD_ISSET(lfd, &rd)) { + n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); + + debug(3, "read(K):%d\n", n1); + + if (n1 <= 0) { + syslog(LOG_ERR, "read error (k-header): %m"); + debug(1, "read error (k-header): %s\n", + STRERROR(errno)); + return; + } + + left = 0; + + switch (do_kbuff(n1, buff, &left)) + { + case R_IO_ERROR : + return; + case R_MORE : + inbuf += left; + break; + default : + inbuf = 0; + break; + } + } + + if (FD_ISSET(nfd, &rd)) { + n1 = recv(nfd, nbuff, sizeof(nbuff), 0); + + debug(3, "read(N):%d\n", n1); + + if (n1 <= 0) { + syslog(LOG_ERR, "read error (n-header): %m"); + debug(1, "read error (n-header): %s\n", + STRERROR(errno)); + return; + } + + switch (do_packet(n1, nbuff)) + { + case R_IO_ERROR : + return; + default : + break; + } + } + } +} + + +int +buildsocket(nicname, sinp) + char *nicname; + struct sockaddr_in *sinp; +{ + struct sockaddr_in *reqip; + struct ifreq req; + char opt; + + debug(2, "binding to %s:%s\n", nicname, inet_ntoa(sinp->sin_addr)); + + if (IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) { + struct in_addr addr; + struct ip_mreq mreq; + + igmpfd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP); + if (igmpfd == -1) { + syslog(LOG_ERR, "socket:%m"); + debug(1, "socket:%s\n", STRERROR(errno)); + return -1; + } + + bzero((char *)&req, sizeof(req)); + strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); + req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; + if (ioctl(igmpfd, SIOCGIFADDR, &req) == -1) { + syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); + debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + reqip = (struct sockaddr_in *)&req.ifr_addr; + + addr = reqip->sin_addr; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_IF, + (char *)&addr, sizeof(addr)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_IF(%s)):%m", + inet_ntoa(addr)); + debug(1, "setsockopt(IP_MULTICAST_IF(%s)):%s\n", + inet_ntoa(addr), STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + opt = 0; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_LOOP, + (char *)&opt, sizeof(opt)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_LOOP=0):%m"); + debug(1, "setsockopt(IP_MULTICAST_LOOP=0):%s\n", + STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + opt = 63; + if (setsockopt(igmpfd, IPPROTO_IP, IP_MULTICAST_TTL, + (char *)&opt, sizeof(opt)) == -1) { + syslog(LOG_ERR, "setsockopt(IP_MULTICAST_TTL=%d):%m", + opt); + debug(1, "setsockopt(IP_MULTICAST_TTL=%d):%s\n", opt, + STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + mreq.imr_multiaddr.s_addr = sinp->sin_addr.s_addr; + mreq.imr_interface.s_addr = reqip->sin_addr.s_addr; + + if (setsockopt(igmpfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&mreq, sizeof(mreq)) == -1) { + char buffer[80]; + + sprintf(buffer, "%s,", inet_ntoa(sinp->sin_addr)); + strcat(buffer, inet_ntoa(reqip->sin_addr)); + + syslog(LOG_ERR, + "setsockpt(IP_ADD_MEMBERSHIP,%s):%m", buffer); + debug(1, "setsockpt(IP_ADD_MEMBERSHIP,%s):%s\n", + buffer, STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + } + nfd = socket(AF_INET, SOCK_DGRAM, 0); + if (nfd == -1) { + syslog(LOG_ERR, "socket:%m"); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + return -1; + } + bzero((char *)&req, sizeof(req)); + strncpy(req.ifr_name, nicname, sizeof(req.ifr_name)); + req.ifr_name[sizeof(req.ifr_name) - 1] = '\0'; + if (ioctl(nfd, SIOCGIFADDR, &req) == -1) { + syslog(LOG_ERR, "ioctl(SIOCGIFADDR):%m"); + debug(1, "ioctl(SIOCGIFADDR):%s\n", STRERROR(errno)); + close(igmpfd); + igmpfd = -1; + return -1; + } + + if (bind(nfd, (struct sockaddr *)&req.ifr_addr, + sizeof(req.ifr_addr)) == -1) { + syslog(LOG_ERR, "bind:%m"); + debug(1, "bind:%s\n", STRERROR(errno)); + close(nfd); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + nfd = -1; + return -1; + } + + if (connect(nfd, (struct sockaddr *)sinp, sizeof(*sinp)) == -1) { + syslog(LOG_ERR, "connect:%m"); + debug(1, "connect:%s\n", STRERROR(errno)); + close(nfd); + if (igmpfd != -1) { + close(igmpfd); + igmpfd = -1; + } + nfd = -1; + return -1; + } + syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sinp->sin_addr)); + debug(3, "Sending data to %s\n", inet_ntoa(sinp->sin_addr)); + + return nfd; +} + + +int +do_packet(pklen, buff) + int pklen; + char *buff; +{ + synchdr_t *sh; + u_32_t magic; + int len; + int n2; + int n3; + + while (pklen > 0) { + if (pklen < sizeof(*sh)) { + syslog(LOG_ERR, "packet length too short:%d", pklen); + debug(2, "packet length too short:%d\n", pklen); + return R_SKIP; + } + + sh = (synchdr_t *)buff; + len = ntohl(sh->sm_len); + magic = ntohl(sh->sm_magic); + + if (magic != SYNHDRMAGIC) { + syslog(LOG_ERR, "invalid header magic %x", magic); + debug(2, "invalid header magic %x\n", magic); + return R_SKIP; + } + + if (pklen < len + sizeof(*sh)) { + syslog(LOG_ERR, "packet length too short:%d", pklen); + debug(2, "packet length too short:%d\n", pklen); + return R_SKIP; + } + + if (debuglevel > 3) { + printsynchdr(sh); + printcommand(sh->sm_cmd); + printtable(sh->sm_table); + printsmcproto(buff); + } + + n2 = sizeof(*sh) + len; + + do { + n3 = write(lfd, buff, n2); + if (n3 <= 0) { + syslog(LOG_ERR, "write error: %m"); + debug(1, "write error: %s\n", STRERROR(errno)); + return R_IO_ERROR; + } + + n2 -= n3; + buff += n3; + pklen -= n3; + } while (n3 != 0); + } + + return R_OKAY; +} + + + +int +do_kbuff(inbuf, buf, left) + int inbuf, *left; + char *buf; +{ + synchdr_t *sh; + u_32_t magic; + int complete; + int sendlen; + int error; + int bytes; + int len; + int n2; + int n3; + + sendlen = 0; + bytes = inbuf; + error = R_OKAY; + sh = (synchdr_t *)buf; + + for (complete = 0; bytes > 0; complete++) { + len = ntohl(sh->sm_len); + magic = ntohl(sh->sm_magic); + + if (magic != SYNHDRMAGIC) { + syslog(LOG_ERR, + "read invalid header magic 0x%x, flushing", + magic); + debug(2, "read invalid header magic 0x%x, flushing\n", + magic); + n2 = SMC_RLOG; + (void) ioctl(lfd, SIOCIPFFL, &n2); + break; + } + + if (debuglevel > 3) { + printsynchdr(sh); + printcommand(sh->sm_cmd); + printtable(sh->sm_table); + putchar('\n'); + } + + if (bytes < sizeof(*sh) + len) { + debug(3, "Not enough bytes %d < %d\n", bytes, + sizeof(*sh) + len); + error = R_MORE; + break; + } + + if (debuglevel > 3) { + printsmcproto(buf); + } + + sendlen += len + sizeof(*sh); + sh = (synchdr_t *)(buf + sendlen); + bytes -= sendlen; + } + + if (complete) { + n3 = send(nfd, buf, sendlen, 0); + if (n3 <= 0) { + syslog(LOG_ERR, "write error: %m"); + debug(1, "write error: %s\n", STRERROR(errno)); + return R_IO_ERROR; + } + debug(3, "send on %d len %d = %d\n", nfd, sendlen, n3); + error = R_OKAY; + } + + /* move buffer to the front,we might need to make + * this more efficient, by using a rolling pointer + * over the buffer and only copying it, when + * we are reaching the end + */ + if (bytes > 0) { + bcopy(buf + bytes, buf, bytes); + error = R_MORE; + } + debug(4, "complete %d bytes %d error %d\n", complete, bytes, error); + + *left = bytes; + + return error; +} + + +void +printcommand(cmd) + int cmd; +{ + + switch (cmd) + { + case SMC_CREATE : + printf(" cmd:CREATE"); + break; + case SMC_UPDATE : + printf(" cmd:UPDATE"); + break; + default : + printf(" cmd:Unknown(%d)", cmd); + break; + } +} + + +void +printtable(table) + int table; +{ + switch (table) + { + case SMC_NAT : + printf(" table:NAT"); + break; + case SMC_STATE : + printf(" table:STATE"); + break; + default : + printf(" table:Unknown(%d)", table); + break; + } +} + + +void +printsmcproto(buff) + char *buff; +{ + syncupdent_t *su; + synchdr_t *sh; + + sh = (synchdr_t *)buff; + + if (sh->sm_cmd == SMC_CREATE) { + ; + + } else if (sh->sm_cmd == SMC_UPDATE) { + su = (syncupdent_t *)buff; + if (sh->sm_p == IPPROTO_TCP) { + printf(" TCP Update: age %lu state %d/%d\n", + su->sup_tcp.stu_age, + su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[1]); + } + } else { + printf("Unknown command\n"); + } +} + + +void +printsynchdr(sh) + synchdr_t *sh; +{ + + printf("v:%d p:%d num:%d len:%d magic:%x", sh->sm_v, sh->sm_p, + ntohl(sh->sm_num), ntohl(sh->sm_len), ntohl(sh->sm_magic)); +} diff --git a/contrib/ipfilter/tools/ipftest.c b/contrib/ipfilter/tools/ipftest.c index 963ed197cb9c..a475828b2e8f 100644 --- a/contrib/ipfilter/tools/ipftest.c +++ b/contrib/ipfilter/tools/ipftest.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -12,24 +12,23 @@ #if !defined(lint) static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipftest.c,v 1.44.2.13 2006/12/12 16:13:01 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; -extern struct frentry *ipfilter[2][2]; -extern struct ipread snoop, etherf, tcpd, pcap, iptext, iphex; +extern struct ipread pcap, iptext, iphex; extern struct ifnet *get_unit __P((char *, int)); extern void init_ifp __P((void)); extern ipnat_t *natparse __P((char *, int)); -extern int fr_running; extern hostmap_t **ipf_hm_maptable; extern hostmap_t *ipf_hm_maplist; -ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert; +ipfmutex_t ipl_mutex, ipf_auth_mx, ipf_rw, ipf_stinsert; ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock; ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ip_poolrw, ipf_frcache; -ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth, ipf_tokens; -int opts = OPT_DONOTHING; +ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_authlk; +ipfrwlock_t ipf_tokens; +int opts = OPT_DONTOPEN; int use_inet6 = 0; int docksum = 0; int pfil_delayed_copy = 0; @@ -37,10 +36,10 @@ int main __P((int, char *[])); int loadrules __P((char *, int)); int kmemcpy __P((char *, long, int)); int kstrncpy __P((char *, long, int n)); -void dumpnat __P((void)); -void dumpstate __P((void)); -void dumplookups __P((void)); -void dumpgroups __P((void)); +int blockreason; +void dumpnat __P((void *)); +void dumpgroups __P((ipf_main_softc_t *)); +void dumprules __P((frentry_t *)); void drain_log __P((char *)); void fixv4sums __P((mb_t *, ip_t *)); @@ -72,18 +71,20 @@ static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl, ipscantestioctl, ipooltestioctl, NULL }; +static ipf_main_softc_t *softc = NULL; -int main(argc,argv) -int argc; -char *argv[]; +int +main(argc,argv) + int argc; + char *argv[]; { char *datain, *iface, *ifname, *logout; int fd, i, dir, c, loaded, dump, hlen; struct in_addr sip; struct ifnet *ifp; struct ipread *r; - mb_t mb, *m; + mb_t mb, *m, *n; ip_t *ip; m = &mb; @@ -98,18 +99,20 @@ char *argv[]; sip.s_addr = 0; ifname = "anon0"; - MUTEX_INIT(&ipf_rw, "ipf rw mutex"); - MUTEX_INIT(&ipf_timeoutlock, "ipf timeout lock"); - RWLOCK_INIT(&ipf_global, "ipf filter load/unload mutex"); - RWLOCK_INIT(&ipf_mutex, "ipf filter rwlock"); - RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock"); - RWLOCK_INIT(&ipf_frcache, "ipf filter cache"); - RWLOCK_INIT(&ipf_tokens, "ipf token rwlock"); - initparse(); - if (fr_initialise() == -1) - abort(); - fr_running = 1; + + ipf_load_all(); + + softc = ipf_create_all(NULL); + if (softc == NULL) + exit(1); + + if (ipf_init_all(softc) == -1) + exit(1); + + i = 1; + if (ipftestioctl(IPL_LOGIPF, SIOCFRENB, &i) != 0) + exit(1); while ((c = getopt(argc, argv, "6bCdDF:i:I:l:N:P:or:RS:T:vxX")) != -1) switch (c) @@ -137,12 +140,6 @@ char *argv[]; case 'F' : if (strcasecmp(optarg, "pcap") == 0) r = &pcap; - else if (strcasecmp(optarg, "etherfind") == 0) - r = ðerf; - else if (strcasecmp(optarg, "snoop") == 0) - r = &snoop; - else if (strcasecmp(optarg, "tcpdump") == 0) - r = &tcpd; else if (strcasecmp(optarg, "hex") == 0) r = &iphex; else if (strcasecmp(optarg, "text") == 0) @@ -208,18 +205,21 @@ char *argv[]; else fd = (*r->r_open)("-"); - if (fd < 0) + if (fd < 0) { + perror("error opening input"); exit(-1); + } + + m->m_data = (char *)m->mb_buf; + while ((i = (*r->r_readip)(m, &iface, &dir)) > 0) { - ip = MTOD(m, ip_t *); - while ((i = (*r->r_readip)(MTOD(m, char *), sizeof(m->mb_buf), - &iface, &dir)) > 0) { if ((iface == NULL) || (*iface == '\0')) iface = ifname; + + ip = MTOD(m, ip_t *); ifp = get_unit(iface, IP_V(ip)); - if (!use_inet6) { - ip->ip_off = ntohs(ip->ip_off); - ip->ip_len = ntohs(ip->ip_len); + + if (IP_V(ip) == 4) { if ((r->r_flags & R_DO_CKSUM) || docksum) fixv4sums(m, ip); hlen = IP_HL(ip) << 2; @@ -231,9 +231,11 @@ char *argv[]; hlen = sizeof(ip6_t); #endif /* ipfr_slowtimer(); */ + blockreason = 0; m = &mb; + m->mb_ifp = ifp; m->mb_len = i; - i = fr_check(ip, hlen, ifp, dir, &m); + i = ipf_check(softc, ip, hlen, ifp, dir, &m); if ((opts & OPT_NAT) == 0) switch (i) { @@ -271,17 +273,24 @@ char *argv[]; (void)printf("recognised return %#x\n", i); break; } - if (!use_inet6) { - ip->ip_off = htons(ip->ip_off); - ip->ip_len = htons(ip->ip_len); - } if (!(opts & OPT_BRIEF)) { putchar(' '); - printpacket(ip); + if (m != NULL) + printpacket(dir, m); + else + printpacket(dir, &mb); printf("--------------"); - } else if ((opts & (OPT_BRIEF|OPT_NAT)) == (OPT_NAT|OPT_BRIEF)) - printpacket(ip); + } else if ((opts & (OPT_BRIEF|OPT_NAT)) == + (OPT_NAT|OPT_BRIEF)) { + if (m != NULL) + printpacket(dir, m); + else + PRINTF("%d\n", blockreason); + } + + ipf_state_flush(softc, 1, 0); + if (dir && (ifp != NULL) && IP_V(ip) && (m != NULL)) #if defined(__sgi) && (IRIX < 60500) (*ifp->if_output)(ifp, (void *)m, NULL); @@ -292,6 +301,13 @@ char *argv[]; (*ifp->if_output)(ifp, (void *)m, NULL, 0); # endif #endif + + while ((m != NULL) && (m != &mb)) { + n = m->mb_next; + freembt(m); + m = n; + } + if ((opts & (OPT_BRIEF|OPT_NAT)) != (OPT_NAT|OPT_BRIEF)) putchar('\n'); dir = 0; @@ -300,6 +316,7 @@ char *argv[]; iface = ifname; } m = &mb; + m->mb_data = (char *)m->mb_buf; } if (i != 0) @@ -311,14 +328,25 @@ char *argv[]; } if (dump == 1) { - dumpnat(); - dumpstate(); - dumplookups(); - dumpgroups(); + dumpnat(softc->ipf_nat_soft); + ipf_state_dump(softc, softc->ipf_state_soft); + ipf_lookup_dump(softc, softc->ipf_state_soft); + dumpgroups(softc); } - fr_deinitialise(); + ipf_fini_all(softc); + + ipf_destroy_all(softc); + + ipf_unload_all(); + ipf_mutex_clean(); + ipf_rwlock_clean(); + + if (getenv("FINDLEAKS")) { + fflush(stdout); + abort(); + } return 0; } @@ -332,14 +360,15 @@ int ipftestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", - (u_int)cmd, data, i); + fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", + (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -354,13 +383,14 @@ int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -376,13 +406,14 @@ int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -398,13 +429,14 @@ int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -420,13 +452,14 @@ int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -442,13 +475,14 @@ int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", + fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; @@ -464,14 +498,15 @@ int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) va_list ap; int i; + dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); - i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); + i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", - (u_int)cmd, data, i); + fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", + (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -480,15 +515,17 @@ int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) } #else int ipftestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGIPF, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(IPF,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", + cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -498,15 +535,16 @@ void *data; int ipnattestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGNAT, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(NAT,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -516,15 +554,16 @@ void *data; int ipstatetestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSTATE, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(STATE,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -534,15 +573,16 @@ void *data; int ipauthtestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGAUTH, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -552,15 +592,16 @@ void *data; int ipsynctestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSYNC, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -570,15 +611,16 @@ void *data; int ipscantestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGSCAN, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) - fprintf(stderr, "iplioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", cmd, data, i); if (i != 0) { errno = i; return -1; @@ -588,15 +630,17 @@ void *data; int ipooltestioctl(dev, cmd, data) -dev_t dev; -ioctlcmd_t cmd; -void *data; + dev_t dev; + ioctlcmd_t cmd; + void *data; { int i; - i = iplioctl(IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); + dev = dev; /* gcc -Wextra */ + i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) - fprintf(stderr, "iplioctl(POOL,%#x,%p) = %d\n", cmd, data, i); + fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", + cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; return -1; @@ -607,9 +651,9 @@ void *data; int kmemcpy(addr, offset, size) -char *addr; -long offset; -int size; + char *addr; + long offset; + int size; { bcopy((char *)offset, addr, size); return 0; @@ -617,9 +661,9 @@ int size; int kstrncpy(buf, pos, n) -char *buf; -long pos; -int n; + char *buf; + long pos; + int n; { char *ptr; @@ -634,100 +678,91 @@ int n; /* * Display the built up NAT table rules and mapping entries. */ -void dumpnat() +void dumpnat(arg) + void *arg; { + ipf_nat_softc_t *softn = arg; hostmap_t *hm; ipnat_t *ipn; nat_t *nat; printf("List of active MAP/Redirect filters:\n"); - for (ipn = nat_list; ipn != NULL; ipn = ipn->in_next) + for (ipn = softn->ipf_nat_list; ipn != NULL; ipn = ipn->in_next) printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); printf("\nList of active sessions:\n"); - for (nat = nat_instances; nat; nat = nat->nat_next) { - printactivenat(nat, opts, 0, 0); + for (nat = softn->ipf_nat_instances; nat; nat = nat->nat_next) { + printactivenat(nat, opts, 0); if (nat->nat_aps) - printaps(nat->nat_aps, opts); + printf("\tproxy active\n"); } printf("\nHostmap table:\n"); - for (hm = ipf_hm_maplist; hm != NULL; hm = hm->hm_next) - printhostmap(hm, 0); -} - - -/* - * Display the built up state table rules and mapping entries. - */ -void dumpstate() -{ - ipstate_t *ips; - - printf("List of active state sessions:\n"); - for (ips = ips_list; ips != NULL; ) - ips = printstate(ips, opts & (OPT_DEBUG|OPT_VERBOSE), - fr_ticks); + for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next) + printhostmap(hm, hm->hm_hv); } -void dumplookups() -{ - iphtable_t *iph; - ip_pool_t *ipl; - int i; - - printf("List of configured pools\n"); - for (i = 0; i < IPL_LOGSIZE; i++) - for (ipl = ip_pool_list[i]; ipl != NULL; ipl = ipl->ipo_next) - printpool(ipl, bcopywrap, NULL, opts); - - printf("List of configured hash tables\n"); - for (i = 0; i < IPL_LOGSIZE; i++) - for (iph = ipf_htables[i]; iph != NULL; iph = iph->iph_next) - printhash(iph, bcopywrap, NULL, opts); -} - - -void dumpgroups() +void dumpgroups(softc) + ipf_main_softc_t *softc; { frgroup_t *fg; - frentry_t *fr; int i; printf("List of groups configured (set 0)\n"); for (i = 0; i < IPL_LOGSIZE; i++) - for (fg = ipfgroups[i][0]; fg != NULL; fg = fg->fg_next) { + for (fg = softc->ipf_groups[i][0]; fg != NULL; + fg = fg->fg_next) { printf("Dev.%d. Group %s Ref %d Flags %#x\n", i, fg->fg_name, fg->fg_ref, fg->fg_flags); - for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { -#ifdef USE_QUAD_T - printf("%qu ",(unsigned long long)fr->fr_hits); -#else - printf("%ld ", fr->fr_hits); -#endif - printfr(fr, ipftestioctl); - } + dumprules(fg->fg_start); } printf("List of groups configured (set 1)\n"); for (i = 0; i < IPL_LOGSIZE; i++) - for (fg = ipfgroups[i][1]; fg != NULL; fg = fg->fg_next) { + for (fg = softc->ipf_groups[i][1]; fg != NULL; + fg = fg->fg_next) { printf("Dev.%d. Group %s Ref %d Flags %#x\n", i, fg->fg_name, fg->fg_ref, fg->fg_flags); - for (fr = fg->fg_start; fr != NULL; fr = fr->fr_next) { + dumprules(fg->fg_start); + } + + printf("Rules configured (set 0, in)\n"); + dumprules(softc->ipf_rules[0][0]); + printf("Rules configured (set 0, out)\n"); + dumprules(softc->ipf_rules[1][0]); + printf("Rules configured (set 1, in)\n"); + dumprules(softc->ipf_rules[0][1]); + printf("Rules configured (set 1, out)\n"); + dumprules(softc->ipf_rules[1][1]); + + printf("Accounting rules configured (set 0, in)\n"); + dumprules(softc->ipf_acct[0][0]); + printf("Accounting rules configured (set 0, out)\n"); + dumprules(softc->ipf_acct[0][1]); + printf("Accounting rules configured (set 1, in)\n"); + dumprules(softc->ipf_acct[1][0]); + printf("Accounting rules configured (set 1, out)\n"); + dumprules(softc->ipf_acct[1][1]); +} + +void dumprules(rulehead) + frentry_t *rulehead; +{ + frentry_t *fr; + + for (fr = rulehead; fr != NULL; fr = fr->fr_next) { #ifdef USE_QUAD_T - printf("%qu ",(unsigned long long)fr->fr_hits); + printf("%"PRIu64" ",(unsigned long long)fr->fr_hits); #else - printf("%ld ", fr->fr_hits); + printf("%ld ", fr->fr_hits); #endif - printfr(fr, ipftestioctl); - } - } + printfr(fr, ipftestioctl); + } } void drain_log(filename) -char *filename; + char *filename; { char buffer[DEFAULT_IPFLOGSIZE]; struct iovec iov; @@ -753,7 +788,7 @@ char *filename; uio.uio_resid = iov.iov_len; resid = uio.uio_resid; - if (ipflog_read(i, &uio) == 0) { + if (ipf_log_read(softc, i, &uio) == 0) { /* * If nothing was read then break out. */ @@ -769,18 +804,38 @@ char *filename; void fixv4sums(m, ip) -mb_t *m; -ip_t *ip; + mb_t *m; + ip_t *ip; { - u_char *csump, *hdr; + u_char *csump, *hdr, p; + fr_info_t tmp; + int len; - ip->ip_sum = 0; - ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); + p = 0; + len = 0; + bzero((char *)&tmp, sizeof(tmp)); csump = (u_char *)ip; - csump += IP_HL(ip) << 2; + if (IP_V(ip) == 4) { + ip->ip_sum = 0; + ip->ip_sum = ipf_cksum((u_short *)ip, IP_HL(ip) << 2); + tmp.fin_hlen = IP_HL(ip) << 2; + csump += IP_HL(ip) << 2; + p = ip->ip_p; + len = ntohs(ip->ip_len); +#ifdef USE_INET6 + } else if (IP_V(ip) == 6) { + tmp.fin_hlen = sizeof(ip6_t); + csump += sizeof(ip6_t); + p = ((ip6_t *)ip)->ip6_nxt; + len = ntohs(((ip6_t *)ip)->ip6_plen); + len += sizeof(ip6_t); +#endif + } + tmp.fin_plen = len; + tmp.fin_dlen = len - tmp.fin_hlen; - switch (ip->ip_p) + switch (p) { case IPPROTO_TCP : hdr = csump; @@ -800,7 +855,12 @@ ip_t *ip; break; } if (hdr != NULL) { + tmp.fin_m = m; + tmp.fin_mp = &m; + tmp.fin_dp = hdr; + tmp.fin_ip = ip; + tmp.fin_plen = len; *csump = 0; - *(u_short *)csump = fr_cksum(m, ip, ip->ip_p, hdr, ip->ip_len); + *(u_short *)csump = fr_cksum(&tmp, ip, p, hdr); } } diff --git a/contrib/ipfilter/tools/ipmon.c b/contrib/ipfilter/tools/ipmon.c index ceaed82cb4b3..1c52e7fd87ac 100644 --- a/contrib/ipfilter/tools/ipmon.c +++ b/contrib/ipfilter/tools/ipmon.c @@ -1,84 +1,22 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ -#ifndef SOLARIS -#define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun) -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/time.h> -#define _KERNEL -#include <sys/uio.h> -#undef _KERNEL -#include <sys/socket.h> +#include "ipf.h" +#include "ipmon.h" #include <sys/ioctl.h> - -#include <stdio.h> -#include <unistd.h> -#include <string.h> +#include <sys/stat.h> +#include <syslog.h> +#include <ctype.h> #include <fcntl.h> -#include <errno.h> -#include <time.h> -#if !defined(__SVR4) && !defined(__svr4__) -# if (__FreeBSD_version >= 300000) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -#endif -#if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__)) -# include <strings.h> -#endif #include <signal.h> -#include <stdlib.h> -#include <stddef.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <net/if.h> -#include <netinet/ip.h> -#if !defined(__hpux) && !defined(linux) -# include <netinet/tcp_fsm.h> -#endif -#include <netdb.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> -#ifdef __hpux -# undef NOERROR -#endif -#include <resolv.h> - -#if !defined(linux) -# include <sys/protosw.h> -# include <netinet/ip_var.h> -#endif - -#include <netinet/tcp.h> -#include <netinet/ip_icmp.h> - -#include <ctype.h> -#include <syslog.h> - -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" -#include "netinet/ip_proxy.h" -#include "ipmon.h" #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.33.2.20 2007/09/20 12:51:56 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -89,12 +27,41 @@ extern char *sys_errlist[]; #define STRERROR(x) strerror(x) #endif +extern int optind; +extern char *optarg; + +extern ipmon_saver_t executesaver; +extern ipmon_saver_t filesaver; +extern ipmon_saver_t nothingsaver; +extern ipmon_saver_t snmpv1saver; +extern ipmon_saver_t snmpv2saver; +extern ipmon_saver_t syslogsaver; + struct flags { int value; char flag; }; +typedef struct logsource { + int fd; + int logtype; + char *file; + int regular; + size_t size; +} logsource_t; + +typedef struct config { + int opts; + int maxfd; + logsource_t logsrc[3]; + fd_set fdmr; + FILE *blog; + char *bfile; + FILE *log; + char *file; + char *cfile; +} config_t; typedef struct icmp_subtype { int ist_val; @@ -124,6 +91,28 @@ struct flags tcpfl[] = { { 0, '\0' } }; +char *reasons[] = { + "filter-rule", + "log-or-block_1", + "pps-rate", + "jumbogram", + "makefrip-fail", + "state_add-fail", + "updateipid-fail", + "log-or-block_2", + "decap-fail", + "auth_new-fail", + "auth_captured", + "coalesce-fail", + "pullup-fail", + "auth-feedback", + "bad-frag", + "natv4_out-fail", + "natv4_in-fail", + "natv6_out-fail", + "natv6_in-fail", +}; + #ifdef MENTAT static char *pidfile = "/etc/opt/ipf/ipmon.pid"; #else @@ -135,18 +124,14 @@ static char *pidfile = "/etc/ipmon.pid"; #endif static char line[2048]; -static int opts = 0; -static char *logfile = NULL; -static FILE *binarylog = NULL; -static char *binarylogfile = NULL; static int donehup = 0; static void usage __P((char *)); static void handlehup __P((int)); static void flushlogs __P((char *, FILE *)); -static void print_log __P((int, FILE *, char *, int)); -static void print_ipflog __P((FILE *, char *, int)); -static void print_natlog __P((FILE *, char *, int)); -static void print_statelog __P((FILE *, char *, int)); +static void print_log __P((config_t *, logsource_t *, char *, int)); +static void print_ipflog __P((config_t *, char *, int)); +static void print_natlog __P((config_t *, char *, int)); +static void print_statelog __P((config_t *, char *, int)); static int read_log __P((int, int *, char *, int)); static void write_pid __P((char *)); static char *icmpname __P((u_int, u_int)); @@ -159,39 +144,30 @@ static struct tm *get_tm __P((u_32_t)); static struct tm *get_tm __P((time_t)); #endif -char *hostname __P((int, int, u_32_t *)); -char *portname __P((int, char *, u_int)); +char *portlocalname __P((int, char *, u_int)); int main __P((int, char *[])); static void logopts __P((int, char *)); static void init_tabs __P((void)); -static char *getproto __P((u_int)); +static char *getlocalproto __P((u_int)); +static void openlogs __P((config_t *conf)); +static int read_loginfo __P((config_t *conf)); +static void initconfig __P((config_t *conf)); static char **protocols = NULL; static char **udp_ports = NULL; static char **tcp_ports = NULL; -static char *conf_file = NULL; -#define OPT_SYSLOG 0x001 -#define OPT_RESOLVE 0x002 -#define OPT_HEXBODY 0x004 -#define OPT_VERBOSE 0x008 -#define OPT_HEXHDR 0x010 -#define OPT_TAIL 0x020 -#define OPT_NAT 0x080 -#define OPT_STATE 0x100 -#define OPT_FILTER 0x200 -#define OPT_PORTNUM 0x400 -#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) -#define OPT_LOGBODY 0x800 - -#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) +#define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b)) #ifndef LOGFAC #define LOGFAC LOG_LOCAL0 #endif int logfac = LOGFAC; +int ipmonopts = 0; +int opts = OPT_NORESOLVE; +int use_inet6 = 0; static icmp_subtype_t icmpunreachnames[] = { @@ -233,7 +209,7 @@ static icmp_subtype_t paramnames[] = { { -2, NULL } }; -static icmp_type_t icmptypes[] = { +static icmp_type_t icmptypes4[] = { { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, { -1, NULL, 0, NULL }, { -1, NULL, 0, NULL }, @@ -338,9 +314,9 @@ static icmp_type_t icmptypes6[] = { }; static icmp_subtype_t *find_icmpsubtype(type, table, tablesz) -int type; -icmp_subtype_t *table; -size_t tablesz; + int type; + icmp_subtype_t *table; + size_t tablesz; { icmp_subtype_t *ist; int i; @@ -363,9 +339,9 @@ size_t tablesz; static icmp_type_t *find_icmptype(type, table, tablesz) -int type; -icmp_type_t *table; -size_t tablesz; + int type; + icmp_type_t *table; + size_t tablesz; { icmp_type_t *it; int i; @@ -388,7 +364,7 @@ size_t tablesz; static void handlehup(sig) -int sig; + int sig; { signal(SIGHUP, handlehup); donehup = 1; @@ -421,12 +397,12 @@ static void init_tabs() p->p_name != NULL && protocols[p->p_proto] == NULL) protocols[p->p_proto] = strdup(p->p_name); endprotoent(); -#if defined(_AIX51) if (protocols[0]) free(protocols[0]); + protocols[0] = strdup("ip"); +#if defined(_AIX51) if (protocols[252]) free(protocols[252]); - protocols[0] = "ip"; protocols[252] = NULL; #endif } @@ -480,8 +456,8 @@ static void init_tabs() } -static char *getproto(p) -u_int p; +static char *getlocalproto(p) + u_int p; { static char pnum[4]; char *s; @@ -497,11 +473,14 @@ u_int p; static int read_log(fd, lenp, buf, bufsize) -int fd, bufsize, *lenp; -char *buf; + int fd, bufsize, *lenp; + char *buf; { int nr; + if (bufsize > IPFILTER_LOGSIZE) + bufsize = IPFILTER_LOGSIZE; + nr = read(fd, buf, bufsize); if (!nr) return 2; @@ -512,51 +491,18 @@ char *buf; } -char *hostname(res, v, ip) -int res, v; -u_32_t *ip; +char *portlocalname(res, proto, port) + int res; + char *proto; + u_int port; { -# define MAX_INETA 16 - static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; -#ifdef USE_INET6 - static char hostbuf[MAXHOSTNAMELEN+1]; -#endif - struct hostent *hp; - struct in_addr ipa; - - if (v == 4) { - ipa.s_addr = *ip; - if (!res) - return inet_ntoa(ipa); - hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); - if (!hp) - return inet_ntoa(ipa); - sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, - inet_ntoa(ipa)); - return hname; - } -#ifdef USE_INET6 - (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); - hostbuf[MAXHOSTNAMELEN] = '\0'; - return hostbuf; -#else - return "IPv6"; -#endif -} - - -char *portname(res, proto, port) -int res; -char *proto; -u_int port; -{ - static char pname[8]; - char *s; + static char pname[8]; + char *s; port = ntohs(port); port &= 0xffff; - (void) sprintf(pname, "%u", port); - if (!res || (opts & OPT_PORTNUM)) + sprintf(pname, "%u", port); + if (!res || (ipmonopts & IPMON_PORTNUM)) return pname; s = NULL; if (!strcmp(proto, "tcp")) @@ -569,9 +515,9 @@ u_int port; } -static char *icmpname(type, code) -u_int type; -u_int code; +static char *icmpname(type, code) + u_int type; + u_int code; { static char name[80]; icmp_subtype_t *ist; @@ -579,7 +525,7 @@ u_int code; char *s; s = NULL; - it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); + it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); if (it != NULL) s = it->it_name; @@ -600,9 +546,9 @@ u_int code; return name; } -static char *icmpname6(type, code) -u_int type; -u_int code; +static char *icmpname6(type, code) + u_int type; + u_int code; { static char name[80]; icmp_subtype_t *ist; @@ -632,11 +578,11 @@ u_int code; } -void dumphex(log, dopts, buf, len) -FILE *log; -int dopts; -char *buf; -int len; +void dumphex(log, dopts, buf, len) + FILE *log; + int dopts; + char *buf; + int len; { char hline[80]; int i, j, k; @@ -651,7 +597,7 @@ int len; if (j && !(j & 0xf)) { *t++ = '\n'; *t = '\0'; - if ((dopts & OPT_SYSLOG)) + if ((dopts & IPMON_SYSLOG)) syslog(LOG_INFO, "%s", hline); else if (log != NULL) fputs(hline, log); @@ -665,10 +611,10 @@ int len; sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); s--; } - + if ((j + 1) & 0xf) *t++ = ' ';; } @@ -683,11 +629,11 @@ int len; t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) - *t++ = (ISPRINT(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } - if ((dopts & OPT_SYSLOG) != 0) + if ((dopts & IPMON_SYSLOG) != 0) syslog(LOG_INFO, "%s", hline); else if (log != NULL) { fputs(hline, log); @@ -696,11 +642,11 @@ int len; } -static struct tm *get_tm(sec) +static struct tm *get_tm(sec) #ifdef __hpux -u_32_t sec; + u_32_t sec; #else -time_t sec; + time_t sec; #endif { struct tm *tm; @@ -711,23 +657,44 @@ time_t sec; return tm; } -static void print_natlog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_natlog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - struct natlog *nl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line; - struct tm *tm; - int res, i, len; - char *proto; + static u_32_t seqnum = 0; + int res, i, len, family; + struct natlog *nl; + struct tm *tm; + iplog_t *ipl; + char *proto; + int simple; + char *t; + + t = line; + simple = 0; + ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u NAT log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u NAT log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); - res = (opts & OPT_RESOLVE) ? 1 : 0; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -735,81 +702,184 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); + sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); t += strlen(t); - if (nl->nl_type == NL_NEWMAP) - strcpy(t, "NAT:MAP "); - else if (nl->nl_type == NL_NEWRDR) - strcpy(t, "NAT:RDR "); - else if (nl->nl_type == NL_FLUSH) - strcpy(t, "NAT:FLUSH "); - else if (nl->nl_type == NL_EXPIRE) - strcpy(t, "NAT:EXPIRE "); - else if (nl->nl_type == NL_NEWBIMAP) - strcpy(t, "NAT:BIMAP "); - else if (nl->nl_type == NL_NEWBLOCK) - strcpy(t, "NAT:MAPBLOCK "); - else if (nl->nl_type == NL_CLONE) - strcpy(t, "NAT:CLONE "); - else if (nl->nl_type == NL_DESTROY) - strcpy(t, "NAT:DESTROY "); - else - sprintf(t, "Type: %d ", nl->nl_type); + switch (nl->nl_action) + { + case NL_NEW : + strcpy(t, "NAT:NEW"); + break; + + case NL_FLUSH : + strcpy(t, "NAT:FLUSH"); + break; + + case NL_CLONE : + strcpy(t, "NAT:CLONE"); + break; + + case NL_EXPIRE : + strcpy(t, "NAT:EXPIRE"); + break; + + case NL_DESTROY : + strcpy(t, "NAT:DESTROY"); + break; + + case NL_PURGE : + strcpy(t, "NAT:PURGE"); + break; + + default : + sprintf(t, "NAT:Action(%d)", nl->nl_action); + break; + } t += strlen(t); - proto = getproto(nl->nl_p); - (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), - portname(res, proto, (u_int)nl->nl_inport)); + switch (nl->nl_type) + { + case NAT_MAP : + strcpy(t, "-MAP "); + simple = 1; + break; + + case NAT_REDIRECT : + strcpy(t, "-RDR "); + simple = 1; + break; + + case NAT_BIMAP : + strcpy(t, "-BIMAP "); + simple = 1; + break; + + case NAT_MAPBLK : + strcpy(t, "-MAPBLOCK "); + simple = 1; + break; + + case NAT_REWRITE|NAT_MAP : + strcpy(t, "-RWR_MAP "); + break; + + case NAT_REWRITE|NAT_REDIRECT : + strcpy(t, "-RWR_RDR "); + break; + + case NAT_ENCAP|NAT_MAP : + strcpy(t, "-ENC_MAP "); + break; + + case NAT_ENCAP|NAT_REDIRECT : + strcpy(t, "-ENC_RDR "); + break; + + case NAT_DIVERTUDP|NAT_MAP : + strcpy(t, "-DIV_MAP "); + break; + + case NAT_DIVERTUDP|NAT_REDIRECT : + strcpy(t, "-DIV_RDR "); + break; + + default : + sprintf(t, "-Type(%d) ", nl->nl_type); + break; + } t += strlen(t); - (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), - portname(res, proto, (u_int)nl->nl_outport)); + + proto = getlocalproto(nl->nl_p[0]); + + family = vtof(nl->nl_v[0]); + + if (simple == 1) { + sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_osrcport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_nsrcport)); + t += strlen(t); + sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), + portlocalname(res, proto, (u_int)nl->nl_odstport)); + } else { + sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_osrcport)); + t += strlen(t); + sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), + portlocalname(res, proto, (u_int)nl->nl_odstport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), + portlocalname(res, proto, (u_int)nl->nl_nsrcport)); + t += strlen(t); + sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), + portlocalname(res, proto, (u_int)nl->nl_ndstport)); + } t += strlen(t); - (void) sprintf(t, "[%s,%s PR %s]", HOSTNAME_V4(res, nl->nl_origip), - portname(res, proto, (u_int)nl->nl_origport), - getproto(nl->nl_p)); + + strcpy(t, getlocalproto(nl->nl_p[0])); t += strlen(t); - if (nl->nl_type == NL_EXPIRE) { + + if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { #ifdef USE_QUAD_T - (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", - (long long)nl->nl_pkts[0], - (long long)nl->nl_pkts[1], - (long long)nl->nl_bytes[0], - (long long)nl->nl_bytes[1]); +# ifdef PRId64 + sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" + PRId64, +# else + sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", +# endif #else - (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", + sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", +#endif nl->nl_pkts[0], nl->nl_pkts[1], nl->nl_bytes[0], nl->nl_bytes[1]); -#endif t += strlen(t); } *t++ = '\n'; *t++ = '\0'; - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + else if (conf->log != NULL) + (void) fprintf(conf->log, "%s", line); } -static void print_statelog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_statelog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - struct ipslog *sl; - iplog_t *ipl = (iplog_t *)buf; - char *t = line, *proto; - struct tm *tm; - int res, i, len; + static u_32_t seqnum = 0; + int res, i, len, family; + struct ipslog *sl; + char *t, *proto; + struct tm *tm; + iplog_t *ipl; + + t = line; + ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u state log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u state log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); - res = (opts & OPT_RESOLVE) ? 1 : 0; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -817,9 +887,11 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); + sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); + family = vtof(sl->isl_v); + switch (sl->isl_type) { case ISL_NEW : @@ -865,41 +937,37 @@ int blen; } t += strlen(t); - proto = getproto(sl->isl_p); + proto = getlocalproto(sl->isl_p); if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { - (void) sprintf(t, "%s,%s -> ", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), - portname(res, proto, (u_int)sl->isl_sport)); + sprintf(t, "%s,%s -> ", + hostname(family, (u_32_t *)&sl->isl_src), + portlocalname(res, proto, (u_int)sl->isl_sport)); t += strlen(t); - (void) sprintf(t, "%s,%s PR %s", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - portname(res, proto, (u_int)sl->isl_dport), proto); + sprintf(t, "%s,%s PR %s", + hostname(family, (u_32_t *)&sl->isl_dst), + portlocalname(res, proto, (u_int)sl->isl_dport), proto); } else if (sl->isl_p == IPPROTO_ICMP) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR icmp %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + sprintf(t, "%s PR icmp %d", + hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else if (sl->isl_p == IPPROTO_ICMPV6) { - (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, - (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 %d", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), + sprintf(t, "%s PR icmpv6 %d", + hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else { - (void) sprintf(t, "%s -> ", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); + sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); - (void) sprintf(t, "%s PR %s", - hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), - proto); + sprintf(t, "%s PR %s", + hostname(family, (u_32_t *)&sl->isl_dst), proto); } t += strlen(t); if (sl->isl_tag != FR_NOLOGTAG) { - (void) sprintf(t, " tag %u", sl->isl_tag); + sprintf(t, " tag %u", sl->isl_tag); t += strlen(t); } if (sl->isl_type != ISL_NEW) { @@ -926,22 +994,26 @@ int blen; *t++ = '\n'; *t++ = '\0'; - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + else if (conf->log != NULL) + (void) fprintf(conf->log, "%s", line); } -static void print_log(logtype, log, buf, blen) -FILE *log; -char *buf; -int logtype, blen; +static void print_log(conf, log, buf, blen) + config_t *conf; + logsource_t *log; + char *buf; + int blen; { + char *bp, *bpo; iplog_t *ipl; - char *bp = NULL, *bpo = NULL; int psize; + bp = NULL; + bpo = NULL; + while (blen > 0) { ipl = (iplog_t *)buf; if ((u_long)ipl & (sizeof(long)-1)) { @@ -961,22 +1033,22 @@ int logtype, blen; if (psize > blen) break; - if (binarylog) { - fwrite(buf, psize, 1, binarylog); - fflush(binarylog); + if (conf->blog != NULL) { + fwrite(buf, psize, 1, conf->blog); + fflush(conf->blog); } - if (logtype == IPL_LOGIPF) { + if (log->logtype == IPL_LOGIPF) { if (ipl->ipl_magic == IPL_MAGIC) - print_ipflog(log, buf, psize); + print_ipflog(conf, buf, psize); - } else if (logtype == IPL_LOGNAT) { + } else if (log->logtype == IPL_LOGNAT) { if (ipl->ipl_magic == IPL_MAGIC_NAT) - print_natlog(log, buf, psize); + print_natlog(conf, buf, psize); - } else if (logtype == IPL_LOGSTATE) { + } else if (log->logtype == IPL_LOGSTATE) { if (ipl->ipl_magic == IPL_MAGIC_STATE) - print_statelog(log, buf, psize); + print_statelog(conf, buf, psize); } blen -= psize; @@ -988,22 +1060,23 @@ int logtype, blen; } -static void print_ipflog(log, buf, blen) -FILE *log; -char *buf; -int blen; +static void print_ipflog(conf, buf, blen) + config_t *conf; + char *buf; + int blen; { - tcphdr_t *tp; - struct icmp *ic; - struct icmp *icmp; - struct tm *tm; - char *t, *proto; - int i, v, lvl, res, len, off, plen, ipoff, defaction; - ip_t *ipc, *ip; - u_32_t *s, *d; - u_short hl, p; + static u_32_t seqnum = 0; + int i, f, lvl, res, len, off, plen, ipoff, defaction; + struct icmp *icmp; + struct icmp *ic; + char *t, *proto; + ip_t *ipc, *ip; + struct tm *tm; + u_32_t *s, *d; + u_short hl, p; ipflog_t *ipf; - iplog_t *ipl; + iplog_t *ipl; + tcphdr_t *tp; #ifdef USE_INET6 struct ip6_ext *ehp; u_short ehl; @@ -1012,16 +1085,31 @@ int blen; #endif ipl = (iplog_t *)buf; + if (ipl->ipl_seqnum != seqnum) { + if ((ipmonopts & IPMON_SYSLOG) != 0) { + syslog(LOG_WARNING, + "missed %u ipf log entries: %u %u", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } else { + (void) fprintf(conf->log, + "missed %u ipf log entries: %u %u\n", + ipl->ipl_seqnum - seqnum, seqnum, + ipl->ipl_seqnum); + } + } + seqnum = ipl->ipl_seqnum + ipl->ipl_count; + ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); ip = (ip_t *)((char *)ipf + sizeof(*ipf)); - v = IP_V(ip); - res = (opts & OPT_RESOLVE) ? 1 : 0; + f = ipf->fl_family; + res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; t = line; *t = '\0'; tm = get_tm(ipl->ipl_sec); len = sizeof(line); - if (!(opts & OPT_SYSLOG)) { + if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; @@ -1029,10 +1117,10 @@ int blen; } (void) strftime(t, len, "%T", tm); t += strlen(t); - (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); + sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); if (ipl->ipl_count > 1) { - (void) sprintf(t, "%dx ", ipl->ipl_count); + sprintf(t, "%dx ", ipl->ipl_count); t += strlen(t); } #if (defined(MENTAT) || \ @@ -1044,13 +1132,19 @@ int blen; strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); ifname[sizeof(ipf->fl_ifname)] = '\0'; - (void) sprintf(t, "%s", ifname); + sprintf(t, "%s", ifname); t += strlen(t); # if defined(MENTAT) || defined(linux) - if (ISALPHA(*(t - 1))) { - sprintf(t, "%d", ipf->fl_unit); - t += strlen(t); - } +# if defined(linux) + /* + * On Linux, the loopback interface is just "lo", not "lo0". + */ + if (strcmp(ifname, "lo") != 0) +# endif + if (ISALPHA(*(t - 1))) { + sprintf(t, "%d", ipf->fl_unit); + t += strlen(t); + } # endif } #else @@ -1059,7 +1153,7 @@ int blen; break; if (ipf->fl_ifname[len]) len++; - (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); + sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); t += strlen(t); #endif if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) @@ -1067,12 +1161,12 @@ int blen; else if (ipf->fl_group[0] == '\0') (void) strcpy(t, " @0:"); else - (void) sprintf(t, " @%s:", ipf->fl_group); + sprintf(t, " @%s:", ipf->fl_group); t += strlen(t); if (ipf->fl_rule == 0xffffffff) strcat(t, "-1 "); else - (void) sprintf(t, "%u ", ipf->fl_rule + 1); + sprintf(t, "%u ", ipf->fl_rule + 1); t += strlen(t); lvl = LOG_NOTICE; @@ -1107,8 +1201,17 @@ int blen; *t++ = ' '; *t = '\0'; - if (v == 6) { + if (f == AF_INET) { + hl = IP_HL(ip) << 2; + ipoff = ntohs(ip->ip_off); + off = ipoff & IP_OFFMASK; + p = (u_short)ip->ip_p; + s = (u_32_t *)&ip->ip_src; + d = (u_32_t *)&ip->ip_dst; + plen = ntohs(ip->ip_len); + } else #ifdef USE_INET6 + if (f == AF_INET6) { off = 0; ipoff = 0; hl = sizeof(ip6_t); @@ -1140,32 +1243,22 @@ int blen; break; } } -#else - sprintf(t, "ipv6"); - goto printipflog; + } else #endif - } else if (v == 4) { - hl = IP_HL(ip) << 2; - ipoff = ip->ip_off; - off = ipoff & IP_OFFMASK; - p = (u_short)ip->ip_p; - s = (u_32_t *)&ip->ip_src; - d = (u_32_t *)&ip->ip_dst; - plen = ip->ip_len; - } else { + { goto printipflog; } - proto = getproto(p); + proto = getlocalproto(p); if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { tp = (tcphdr_t *)((char *)ip + hl); if (!(ipf->fl_lflags & FI_SHORT)) { - (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), - portname(res, proto, (u_int)tp->th_sport)); + sprintf(t, "%s,%s -> ", hostname(f, s), + portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); - (void) sprintf(t, "%s,%s PR %s len %hu %hu", - hostname(res, v, d), - portname(res, proto, (u_int)tp->th_dport), + sprintf(t, "%s,%s PR %s len %hu %hu", + hostname(f, d), + portlocalname(res, proto, (u_int)tp->th_dport), proto, hl, plen); t += strlen(t); @@ -1175,8 +1268,8 @@ int blen; for (i = 0; tcpfl[i].value; i++) if (tp->th_flags & tcpfl[i].value) *t++ = tcpfl[i].flag; - if (opts & OPT_VERBOSE) { - (void) sprintf(t, " %lu %lu %hu", + if (ipmonopts & IPMON_VERBOSE) { + sprintf(t, " %lu %lu %hu", (u_long)(ntohl(tp->th_seq)), (u_long)(ntohl(tp->th_ack)), ntohs(tp->th_win)); @@ -1185,24 +1278,26 @@ int blen; } *t = '\0'; } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu %hu", - hostname(res, v, d), proto, hl, plen); + sprintf(t, "%s PR %s len %hu %hu", + hostname(f, d), proto, hl, plen); } - } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { +#if defined(AF_INET6) && defined(IPPROTO_ICMPV6) + } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", - hostname(res, v, d), hl, plen, + sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", + hostname(f, d), hl, plen, icmpname6(ic->icmp_type, ic->icmp_code)); - } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { +#endif + } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { ic = (struct icmp *)((char *)ip + hl); - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", - hostname(res, v, d), hl, plen, + sprintf(t, "%s PR icmp len %hu %hu icmp %s", + hostname(f, d), hl, plen, icmpname(ic->icmp_type, ic->icmp_code)); if (ic->icmp_type == ICMP_UNREACH || ic->icmp_type == ICMP_SOURCEQUENCH || @@ -1218,21 +1313,21 @@ int blen; if (i > 1500) i = ipc->ip_len; ipoff = ntohs(ipc->ip_off); - proto = getproto(ipc->ip_p); + proto = getlocalproto(ipc->ip_p); if (!(ipoff & IP_OFFMASK) && ((ipc->ip_p == IPPROTO_TCP) || (ipc->ip_p == IPPROTO_UDP))) { tp = (tcphdr_t *)((char *)ipc + hl); t += strlen(t); - (void) sprintf(t, " for %s,%s -", - HOSTNAME_V4(res, ipc->ip_src), - portname(res, proto, + sprintf(t, " for %s,%s -", + HOSTNAMEV4(ipc->ip_src), + portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); - (void) sprintf(t, " %s,%s PR %s len %hu %hu", - HOSTNAME_V4(res, ipc->ip_dst), - portname(res, proto, + sprintf(t, " %s,%s PR %s len %hu %hu", + HOSTNAMEV4(ipc->ip_dst), + portlocalname(res, proto, (u_int)tp->th_dport), proto, IP_HL(ipc) << 2, i); } else if (!(ipoff & IP_OFFMASK) && @@ -1240,26 +1335,25 @@ int blen; icmp = (icmphdr_t *)((char *)ipc + hl); t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); + sprintf(t, " for %s -", + HOSTNAMEV4(ipc->ip_src)); t += strlen(t); - (void) sprintf(t, + sprintf(t, " %s PR icmp len %hu %hu icmp %d/%d", - HOSTNAME_V4(res, ipc->ip_dst), + HOSTNAMEV4(ipc->ip_dst), IP_HL(ipc) << 2, i, icmp->icmp_type, icmp->icmp_code); } else { t += strlen(t); - (void) sprintf(t, " for %s -", - HOSTNAME_V4(res, ipc->ip_src)); + sprintf(t, " for %s -", + HOSTNAMEV4(ipc->ip_src)); t += strlen(t); - (void) sprintf(t, " %s PR %s len %hu (%hu)", - HOSTNAME_V4(res, ipc->ip_dst), proto, + sprintf(t, " %s PR %s len %hu (%hu)", + HOSTNAMEV4(ipc->ip_dst), proto, IP_HL(ipc) << 2, i); t += strlen(t); if (ipoff & IP_OFFMASK) { - (void) sprintf(t, - "(frag %d:%hu@%hu%s%s)", + sprintf(t, "(frag %d:%hu@%hu%s%s)", ntohs(ipc->ip_id), i - (IP_HL(ipc) << 2), (ipoff & IP_OFFMASK) << 3, @@ -1270,13 +1364,13 @@ int blen; } } else { - (void) sprintf(t, "%s -> ", hostname(res, v, s)); + sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); - (void) sprintf(t, "%s PR %s len %hu (%hu)", - hostname(res, v, d), proto, hl, plen); + sprintf(t, "%s PR %s len %hu (%hu)", + hostname(f, d), proto, hl, plen); t += strlen(t); if (off & IP_OFFMASK) - (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", + sprintf(t, " (frag %d:%hu@%hu%s%s)", ntohs(ip->ip_id), plen - hl, (off & IP_OFFMASK) << 3, ipoff & IP_MF ? "+" : "", @@ -1347,32 +1441,43 @@ printipflog: strcpy(t, " mbcast"); t += 7; } + if (ipf->fl_breason != 0) { + strcpy(t, " reason:"); + t += 8; + strcpy(t, reasons[ipf->fl_breason]); + t += strlen(reasons[ipf->fl_breason]); + } *t++ = '\n'; *t++ = '\0'; defaction = 0; - if (conf_file != NULL) - defaction = check_action(buf, line, opts, lvl); + if (conf->cfile != NULL) + defaction = check_action(buf, line, ipmonopts, lvl); + if (defaction == 0) { - if (opts & OPT_SYSLOG) + if (ipmonopts & IPMON_SYSLOG) { syslog(lvl, "%s", line); - else if (log != NULL) - (void) fprintf(log, "%s", line); + } else if (conf->log != NULL) { + (void) fprintf(conf->log, "%s", line); + } - if (opts & OPT_HEXHDR) - dumphex(log, opts, buf, + if (ipmonopts & IPMON_HEXHDR) { + dumphex(conf->log, ipmonopts, buf, sizeof(iplog_t) + sizeof(*ipf)); - if (opts & OPT_HEXBODY) - dumphex(log, opts, (char *)ip, + } + if (ipmonopts & IPMON_HEXBODY) { + dumphex(conf->log, ipmonopts, (char *)ip, ipf->fl_plen + ipf->fl_hlen); - else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) - dumphex(log, opts, (char *)ip + ipf->fl_hlen, + } else if ((ipmonopts & IPMON_LOGBODY) && + (ipf->fl_flags & FR_LOGBODY)) { + dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, ipf->fl_plen); + } } } static void usage(prog) -char *prog; + char *prog; { fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); exit(1); @@ -1380,7 +1485,7 @@ char *prog; static void write_pid(file) -char *file; + char *file; { FILE *fp = NULL; int fd; @@ -1400,8 +1505,8 @@ char *file; static void flushlogs(file, log) -char *file; -FILE *log; + char *file; + FILE *log; { int fd, flushed = 0; @@ -1416,11 +1521,11 @@ FILE *log; flushed); fflush(stdout); } else - perror("SIOCIPFFB"); + ipferror(fd, "SIOCIPFFB"); (void) close(fd); if (flushed) { - if (opts & OPT_SYSLOG) { + if (ipmonopts & IPMON_SYSLOG) { syslog(LOG_INFO, "%d bytes flushed from log\n", flushed); } else if ((log != stdout) && (log != NULL)) { @@ -1431,8 +1536,8 @@ FILE *log; static void logopts(turnon, options) -int turnon; -char *options; + int turnon; + char *options; { int flags = 0; char *s; @@ -1442,13 +1547,13 @@ char *options; switch (*s) { case 'N' : - flags |= OPT_NAT; + flags |= IPMON_NAT; break; case 'S' : - flags |= OPT_STATE; + flags |= IPMON_STATE; break; case 'I' : - flags |= OPT_FILTER; + flags |= IPMON_FILTER; break; default : fprintf(stderr, "Unknown log option %c\n", *s); @@ -1457,64 +1562,87 @@ char *options; } if (turnon) - opts |= flags; + ipmonopts |= flags; else - opts &= ~(flags); + ipmonopts &= ~(flags); +} + +static void initconfig(config_t *conf) +{ + int i; + + memset(conf, 0, sizeof(*conf)); + + conf->log = stdout; + conf->maxfd = -1; + + for (i = 0; i < 3; i++) { + conf->logsrc[i].fd = -1; + conf->logsrc[i].logtype = -1; + conf->logsrc[i].regular = -1; + } + + conf->logsrc[0].file = IPL_NAME; + conf->logsrc[1].file = IPNAT_NAME; + conf->logsrc[2].file = IPSTATE_NAME; + + add_doing(&executesaver); + add_doing(&snmpv1saver); + add_doing(&snmpv2saver); + add_doing(&syslogsaver); + add_doing(&filesaver); + add_doing(¬hingsaver); } int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - struct stat sb; - FILE *log = stdout; - FILE *fp; - int fd[3], doread, n, i; - int tr, nr, regular[3], c; - int fdt[3], devices = 0, make_daemon = 0; - char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; - extern int optind; - extern char *optarg; + int doread, c, make_daemon = 0; + char *prog; + config_t config; + + prog = strrchr(argv[0], '/'); + if (prog == NULL) + prog = argv[0]; + else + prog++; - fd[0] = fd[1] = fd[2] = -1; - fdt[0] = fdt[1] = fdt[2] = -1; - iplfile[0] = IPL_NAME; - iplfile[1] = IPNAT_NAME; - iplfile[2] = IPSTATE_NAME; + initconfig(&config); while ((c = getopt(argc, argv, "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) switch (c) { case 'a' : - opts |= OPT_LOGALL; - fdt[0] = IPL_LOGIPF; - fdt[1] = IPL_LOGNAT; - fdt[2] = IPL_LOGSTATE; + ipmonopts |= IPMON_LOGALL; + config.logsrc[0].logtype = IPL_LOGIPF; + config.logsrc[1].logtype = IPL_LOGNAT; + config.logsrc[2].logtype = IPL_LOGSTATE; break; case 'b' : - opts |= OPT_LOGBODY; + ipmonopts |= IPMON_LOGBODY; break; case 'B' : - binarylogfile = optarg; - binarylog = fopen(optarg, "a"); + config.bfile = optarg; + config.blog = fopen(optarg, "a"); break; case 'C' : - conf_file = optarg; + config.cfile = optarg; break; case 'D' : make_daemon = 1; break; case 'f' : case 'I' : - opts |= OPT_FILTER; - fdt[0] = IPL_LOGIPF; - iplfile[0] = optarg; + ipmonopts |= IPMON_FILTER; + config.logsrc[0].logtype = IPL_LOGIPF; + config.logsrc[0].file = optarg; break; case 'F' : - flushlogs(iplfile[0], log); - flushlogs(iplfile[1], log); - flushlogs(iplfile[2], log); + flushlogs(config.logsrc[0].file, config.log); + flushlogs(config.logsrc[1].file, config.log); + flushlogs(config.logsrc[2].file, config.log); break; case 'L' : logfac = fac_findname(optarg); @@ -1526,56 +1654,49 @@ char *argv[]; } break; case 'n' : - opts |= OPT_RESOLVE; + ipmonopts |= IPMON_RESOLVE; + opts &= ~OPT_NORESOLVE; break; case 'N' : - opts |= OPT_NAT; - fdt[1] = IPL_LOGNAT; - iplfile[1] = optarg; + ipmonopts |= IPMON_NAT; + config.logsrc[1].logtype = IPL_LOGNAT; + config.logsrc[1].file = optarg; break; case 'o' : case 'O' : logopts(c == 'o', optarg); - fdt[0] = fdt[1] = fdt[2] = -1; - if (opts & OPT_FILTER) - fdt[0] = IPL_LOGIPF; - if (opts & OPT_NAT) - fdt[1] = IPL_LOGNAT; - if (opts & OPT_STATE) - fdt[2] = IPL_LOGSTATE; + if (ipmonopts & IPMON_FILTER) + config.logsrc[0].logtype = IPL_LOGIPF; + if (ipmonopts & IPMON_NAT) + config.logsrc[1].logtype = IPL_LOGNAT; + if (ipmonopts & IPMON_STATE) + config.logsrc[2].logtype = IPL_LOGSTATE; break; case 'p' : - opts |= OPT_PORTNUM; + ipmonopts |= IPMON_PORTNUM; break; case 'P' : pidfile = optarg; break; case 's' : - s = strrchr(argv[0], '/'); - if (s == NULL) - s = argv[0]; - else - s++; - openlog(s, LOG_NDELAY|LOG_PID, logfac); - s = NULL; - opts |= OPT_SYSLOG; - log = NULL; + ipmonopts |= IPMON_SYSLOG; + config.log = NULL; break; case 'S' : - opts |= OPT_STATE; - fdt[2] = IPL_LOGSTATE; - iplfile[2] = optarg; + ipmonopts |= IPMON_STATE; + config.logsrc[2].logtype = IPL_LOGSTATE; + config.logsrc[2].file = optarg; break; case 't' : - opts |= OPT_TAIL; + ipmonopts |= IPMON_TAIL; break; case 'v' : - opts |= OPT_VERBOSE; + ipmonopts |= IPMON_VERBOSE; break; case 'x' : - opts |= OPT_HEXBODY; + ipmonopts |= IPMON_HEXBODY; break; case 'X' : - opts |= OPT_HEXHDR; + ipmonopts |= IPMON_HEXHDR; break; default : case 'h' : @@ -1583,69 +1704,62 @@ char *argv[]; usage(argv[0]); } + if (ipmonopts & IPMON_SYSLOG) + openlog(prog, LOG_NDELAY|LOG_PID, logfac); + init_tabs(); - if (conf_file) - if (load_config(conf_file) == -1) + if (config.cfile) + if (load_config(config.cfile) == -1) { + unload_config(); exit(1); + } /* * Default action is to only open the filter log file. */ - if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) - fdt[0] = IPL_LOGIPF; + if ((config.logsrc[0].logtype == -1) && + (config.logsrc[0].logtype == -1) && + (config.logsrc[0].logtype == -1)) + config.logsrc[0].logtype = IPL_LOGIPF; - for (i = 0; i < 3; i++) { - if (fdt[i] == -1) - continue; - if (!strcmp(iplfile[i], "-")) - fd[i] = 0; - else { - if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { - (void) fprintf(stderr, - "%s: open: %s\n", iplfile[i], - STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (fstat(fd[i], &sb) == -1) { - (void) fprintf(stderr, "%d: fstat: %s\n", - fd[i], STRERROR(errno)); - exit(1); - /* NOTREACHED */ - } - if (!(regular[i] = !S_ISCHR(sb.st_mode))) - devices++; - } - } + openlogs(&config); - if (!(opts & OPT_SYSLOG)) { - logfile = argv[optind]; - log = logfile ? fopen(logfile, "a") : stdout; - if (log == NULL) { + if (!(ipmonopts & IPMON_SYSLOG)) { + config.file = argv[optind]; + config.log = config.file ? fopen(config.file, "a") : stdout; + if (config.log == NULL) { (void) fprintf(stderr, "%s: fopen: %s\n", argv[optind], STRERROR(errno)); exit(1); /* NOTREACHED */ } - setvbuf(log, NULL, _IONBF, 0); - } else - log = NULL; + setvbuf(config.log, NULL, _IONBF, 0); + } else { + config.log = NULL; + } - if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { + if (make_daemon && + ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { #if BSD >= 199306 - daemon(0, !(opts & OPT_SYSLOG)); + daemon(0, !(ipmonopts & IPMON_SYSLOG)); #else int pid; - if ((pid = fork()) > 0) - exit(0); - if (pid < 0) { + + switch (fork()) + { + case -1 : (void) fprintf(stderr, "%s: fork() failed: %s\n", argv[0], STRERROR(errno)); exit(1); /* NOTREACHED */ + case 0 : + break; + default : + exit(0); } + setsid(); - if ((opts & OPT_SYSLOG)) + if ((ipmonopts & IPMON_SYSLOG)) close(2); #endif /* !BSD */ close(0); @@ -1655,80 +1769,142 @@ char *argv[]; signal(SIGHUP, handlehup); - for (doread = 1; doread; ) { - nr = 0; + for (doread = 1; doread; ) + doread = read_loginfo(&config); - for (i = 0; i < 3; i++) { - tr = 0; - if (fdt[i] == -1) - continue; - if (!regular[i]) { - if (ioctl(fd[i], FIONREAD, &tr) == -1) { - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, - "ioctl(FIONREAD): %m"); - else - perror("ioctl(FIONREAD)"); - exit(1); - /* NOTREACHED */ - } - } else { - tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); - if (!tr && !(opts & OPT_TAIL)) - doread = 0; + unload_config(); + + return(0); + /* NOTREACHED */ +} + + +static void openlogs(config_t *conf) +{ + logsource_t *l; + struct stat sb; + int i; + + for (i = 0; i < 3; i++) { + l = &conf->logsrc[i]; + if (l->logtype == -1) + continue; + if (!strcmp(l->file, "-")) + l->fd = 0; + else { + if ((l->fd= open(l->file, O_RDONLY)) == -1) { + (void) fprintf(stderr, + "%s: open: %s\n", l->file, + STRERROR(errno)); + exit(1); + /* NOTREACHED */ } - if (!tr) - continue; - nr += tr; - n = 0; - tr = read_log(fd[i], &n, buf, sizeof(buf)); - if (donehup) { - if (logfile && (fp = fopen(logfile, "a"))) { - fclose(log); - log = fp; - } - if (binarylogfile && - (fp = fopen(binarylogfile, "a"))) { - fclose(binarylog); - binarylog = fp; + if (fstat(l->fd, &sb) == -1) { + (void) fprintf(stderr, "%d: fstat: %s\n", + l->fd, STRERROR(errno)); + exit(1); + /* NOTREACHED */ + } + + l->regular = !S_ISCHR(sb.st_mode); + if (l->regular) + l->size = sb.st_size; + + FD_SET(l->fd, &conf->fdmr); + if (l->fd > conf->maxfd) + conf->maxfd = l->fd; + } + } +} + + +static int read_loginfo(config_t *conf) +{ + iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; + int n, tr, nr, i; + logsource_t *l; + fd_set fdr; + + fdr = conf->fdmr; + + n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); + if (n == 0) + return 1; + if (n == -1) { + if (errno == EINTR) + return 1; + return -1; + } + + for (i = 0, nr = 0; i < 3; i++) { + l = &conf->logsrc[i]; + + if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) + continue; + + tr = 0; + if (l->regular) { + tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); + if (!tr && !(ipmonopts & IPMON_TAIL)) + return 0; + } + + n = 0; + tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); + if (donehup) { + if (conf->file != NULL) { + if (conf->log != NULL) { + fclose(conf->log); + conf->log = NULL; } - init_tabs(); - if (conf_file != NULL) - load_config(conf_file); - donehup = 0; + conf->log = fopen(conf->file, "a"); } - switch (tr) - { - case -1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "read: %m\n"); - else - perror("read"); - doread = 0; - break; - case 1 : - if (opts & OPT_SYSLOG) - syslog(LOG_CRIT, "aborting logging\n"); - else if (log != NULL) - fprintf(log, "aborting logging\n"); - doread = 0; - break; - case 2 : - break; - case 0 : - if (n > 0) { - print_log(fdt[i], log, buf, n); - if (!(opts & OPT_SYSLOG)) - fflush(log); + if (conf->bfile != NULL) { + if (conf->blog != NULL) { + fclose(conf->blog); + conf->blog = NULL; } - break; + conf->blog = fopen(conf->bfile, "a"); } + + init_tabs(); + if (conf->cfile != NULL) + load_config(conf->cfile); + donehup = 0; + } + + switch (tr) + { + case -1 : + if (ipmonopts & IPMON_SYSLOG) + syslog(LOG_CRIT, "read: %m\n"); + else { + ipferror(l->fd, "read"); + } + return 0; + case 1 : + if (ipmonopts & IPMON_SYSLOG) + syslog(LOG_CRIT, "aborting logging\n"); + else if (conf->log != NULL) + fprintf(conf->log, "aborting logging\n"); + return 0; + case 2 : + break; + case 0 : + nr += tr; + if (n > 0) { + print_log(conf, l, (char *)buf, n); + if (!(ipmonopts & IPMON_SYSLOG)) + fflush(conf->log); + } + break; } - if (!nr && ((opts & OPT_TAIL) || devices)) - sleep(1); } - return(0); - /* NOTREACHED */ + + if (!nr && (ipmonopts & IPMON_TAIL)) + sleep(1); + + return 1; } diff --git a/contrib/ipfilter/tools/ipmon_y.y b/contrib/ipfilter/tools/ipmon_y.y index 98042d880222..f14180d6a9e9 100644 --- a/contrib/ipfilter/tools/ipmon_y.y +++ b/contrib/ipfilter/tools/ipmon_y.y @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -13,6 +13,8 @@ #include "ipmon_l.h" #include "ipmon.h" +#include <dlfcn.h> + #define YYDEBUG 1 extern void yyerror __P((char *)); @@ -21,69 +23,88 @@ extern int yylex __P((void)); extern int yydebug; extern FILE *yyin; extern int yylineNum; +extern int ipmonopts; -typedef struct opt { - struct opt *o_next; +typedef struct opt_s { + struct opt_s *o_next; int o_line; int o_type; int o_num; char *o_str; struct in_addr o_ip; + int o_logfac; + int o_logpri; } opt_t; -static void build_action __P((struct opt *)); +static void build_action __P((opt_t *, ipmon_doing_t *)); static opt_t *new_opt __P((int)); static void free_action __P((ipmon_action_t *)); +static void print_action __P((ipmon_action_t *)); +static int find_doing __P((char *)); +static ipmon_doing_t *build_doing __P((char *, char *)); +static void print_match __P((ipmon_action_t *)); +static int install_saver __P((char *, char *)); static ipmon_action_t *alist = NULL; + +ipmon_saver_int_t *saverlist = NULL; %} %union { char *str; u_32_t num; struct in_addr addr; - struct opt *opt; + struct opt_s *opt; union i6addr ip6; + struct ipmon_doing_s *ipmd; } %token <num> YY_NUMBER YY_HEX %token <str> YY_STR %token <ip6> YY_IPV6 -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT -%token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT +%token IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION %token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE %token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH -%token IPM_DO IPM_SAVE IPM_SYSLOG IPM_NOTHING IPM_RAW IPM_TYPE IPM_NAT +%token IPM_DO IPM_DOING IPM_TYPE IPM_NAT %token IPM_STATE IPM_NATTAG IPM_IPF %type <addr> ipv4 -%type <opt> direction dstip dstport every execute group interface +%type <opt> direction dstip dstport every group interface %type <opt> protocol result rule srcip srcport logtag matching -%type <opt> matchopt nattag type doopt doing save syslog nothing -%type <num> saveopts saveopt typeopt +%type <opt> matchopt nattag type +%type <num> typeopt +%type <ipmd> doopt doing %% -file: line - | assign - | file line - | file assign +file: action + | file action ; -line: IPM_MATCH '{' matching '}' IPM_DO '{' doing '}' ';' - { build_action($3); resetlexer(); } +action: line ';' + | assign ';' | IPM_COMMENT | YY_COMMENT ; -assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); +line: IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}' + { build_action($3, $8); + resetlexer(); + } + | IPM_LOADACTION YY_STR YY_STR { if (install_saver($2, $3)) + yyerror("install saver"); + } + ; + +assign: YY_STR assigning YY_STR { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; - } + } ; assigning: @@ -114,14 +135,20 @@ matchopt: doing: doopt { $$ = $1; } - | doopt ',' doing { $1->o_next = $3; $$ = $1; } + | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } ; doopt: - execute { $$ = $1; } - | save { $$ = $1; } - | syslog { $$ = $1; } - | nothing { $$ = $1; } + YY_STR { if (find_doing($1) != IPM_DOING) + yyerror("unknown action"); + } + '(' YY_STR ')' { $$ = build_doing($1, $4); + if ($$ == NULL) + yyerror("action building"); + } + | YY_STR { if (find_doing($1) == IPM_DOING) + $$ = build_doing($1, NULL); + } ; direction: @@ -211,31 +238,7 @@ typeopt: | IPM_STATE { $$ = IPL_MAGIC_STATE; } ; -execute: - IPM_EXECUTE YY_STR { $$ = new_opt(IPM_EXECUTE); - $$->o_str = $2; } - ; - -save: IPM_SAVE saveopts YY_STR { $$ = new_opt(IPM_SAVE); - $$->o_num = $2; - $$->o_str = $3; } - ; - -saveopts: { $$ = 0; } - | saveopt { $$ = $1; } - | saveopt ',' saveopts { $$ = $1 | $3; } - ; - -saveopt: - IPM_RAW { $$ = IPMDO_SAVERAW; } - ; - -syslog: IPM_SYSLOG { $$ = new_opt(IPM_SYSLOG); } - ; -nothing: - IPM_NOTHING { $$ = 0; } - ; ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { @@ -253,30 +256,27 @@ static struct wordtab yywords[] = { { "dstip", IPM_DSTIP }, { "dstport", IPM_DSTPORT }, { "every", IPM_EVERY }, - { "execute", IPM_EXECUTE }, { "group", IPM_GROUP }, { "in", IPM_IN }, { "interface", IPM_INTERFACE }, { "ipf", IPM_IPF }, + { "load_action",IPM_LOADACTION }, { "logtag", IPM_LOGTAG }, { "match", IPM_MATCH }, { "nat", IPM_NAT }, { "nattag", IPM_NATTAG }, { "no", IPM_NO }, - { "nothing", IPM_NOTHING }, { "out", IPM_OUT }, { "packet", IPM_PACKET }, { "packets", IPM_PACKETS }, { "protocol", IPM_PROTOCOL }, { "result", IPM_RESULT }, { "rule", IPM_RULE }, - { "save", IPM_SAVE }, { "second", IPM_SECOND }, { "seconds", IPM_SECONDS }, { "srcip", IPM_SRCIP }, { "srcport", IPM_SRCPORT }, { "state", IPM_STATE }, - { "syslog", IPM_SYSLOG }, { "with", IPM_WITH }, { NULL, 0 } }; @@ -301,31 +301,33 @@ static int macflags[17][2] = { { 0, 0 } }; -static opt_t *new_opt(type) -int type; +static opt_t * +new_opt(type) + int type; { opt_t *o; - o = (opt_t *)malloc(sizeof(*o)); + o = (opt_t *)calloc(1, sizeof(*o)); o->o_type = type; o->o_line = yylineNum; - o->o_num = 0; - o->o_str = (char *)0; - o->o_next = NULL; + o->o_logfac = -1; + o->o_logpri = -1; return o; } -static void build_action(olist) -opt_t *olist; +static void +build_action(olist, todo) + opt_t *olist; + ipmon_doing_t *todo; { ipmon_action_t *a; opt_t *o; - char c; int i; a = (ipmon_action_t *)calloc(1, sizeof(*a)); if (a == NULL) return; + while ((o = olist) != NULL) { /* * Check to see if the same comparator is being used more than @@ -358,24 +360,11 @@ opt_t *olist; case IPM_DSTPORT : a->ac_dport = htons(o->o_num); break; - case IPM_EXECUTE : - a->ac_exec = o->o_str; - c = *o->o_str; - if (c== '"'|| c == '\'') { - if (o->o_str[strlen(o->o_str) - 1] == c) { - a->ac_run = strdup(o->o_str + 1); - a->ac_run[strlen(a->ac_run) - 1] ='\0'; - } else - a->ac_run = o->o_str; - } else - a->ac_run = o->o_str; - o->o_str = NULL; - break; case IPM_INTERFACE : a->ac_iface = o->o_str; o->o_str = NULL; break; - case IPM_GROUP : + case IPM_GROUP : if (o->o_str != NULL) strncpy(a->ac_group, o->o_str, FR_GROUPLEN); else @@ -416,24 +405,6 @@ opt_t *olist; case IPM_SRCPORT : a->ac_sport = htons(o->o_num); break; - case IPM_SAVE : - if (a->ac_savefile != NULL) { - fprintf(stderr, "%s redfined on line %d\n", - yykeytostr(o->o_type), yylineNum); - break; - } - a->ac_savefile = strdup(o->o_str); - a->ac_savefp = fopen(o->o_str, "a"); - a->ac_dflag |= o->o_num & IPMDO_SAVERAW; - break; - case IPM_SYSLOG : - if (a->ac_syslog != 0) { - fprintf(stderr, "%s redfined on line %d\n", - yykeytostr(o->o_type), yylineNum); - break; - } - a->ac_syslog = 1; - break; case IPM_TYPE : a->ac_type = o->o_num; break; @@ -448,17 +419,25 @@ opt_t *olist; free(o->o_str); free(o); } + + a->ac_doing = todo; a->ac_next = alist; alist = a; + + if (ipmonopts & IPMON_VERBOSE) + print_action(a); } -int check_action(buf, log, opts, lvl) -char *buf, *log; -int opts, lvl; +int +check_action(buf, log, opts, lvl) + char *buf, *log; + int opts, lvl; { ipmon_action_t *a; struct timeval tv; + ipmon_doing_t *d; + ipmon_msg_t msg; ipflog_t *ipf; tcphdr_t *tcp; iplog_t *ipl; @@ -472,19 +451,33 @@ int opts, lvl; ip = (ip_t *)(ipf + 1); tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); + msg.imm_data = ipl; + msg.imm_dsize = ipl->ipl_dsize; + msg.imm_when = ipl->ipl_time.tv_sec; + msg.imm_msg = log; + msg.imm_msglen = strlen(log); + msg.imm_loglevel = lvl; + for (a = alist; a != NULL; a = a->ac_next) { + verbose(0, "== checking config rule\n"); if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { if (a->ac_direction == IPM_IN) { - if ((ipf->fl_flags & FR_INQUE) == 0) + if ((ipf->fl_flags & FR_INQUE) == 0) { + verbose(8, "-- direction not in\n"); continue; + } } else if (a->ac_direction == IPM_OUT) { - if ((ipf->fl_flags & FR_OUTQUE) == 0) + if ((ipf->fl_flags & FR_OUTQUE) == 0) { + verbose(8, "-- direction not out\n"); continue; + } } } - if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) + if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) { + verbose(8, "-- type mismatch\n"); continue; + } if ((a->ac_mflag & IPMAC_EVERY) != 0) { gettimeofday(&tv, NULL); @@ -492,8 +485,10 @@ int opts, lvl; if (tv.tv_usec <= a->ac_lastusec) t1--; if (a->ac_second != 0) { - if (t1 < a->ac_second) + if (t1 < a->ac_second) { + verbose(8, "-- too soon\n"); continue; + } a->ac_lastsec = tv.tv_sec; a->ac_lastusec = tv.tv_usec; } @@ -503,159 +498,149 @@ int opts, lvl; a->ac_pktcnt++; else if (a->ac_pktcnt == a->ac_packet) { a->ac_pktcnt = 0; + verbose(8, "-- packet count\n"); continue; } else { a->ac_pktcnt++; + verbose(8, "-- packet count\n"); continue; } } } if ((a->ac_mflag & IPMAC_DSTIP) != 0) { - if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) + if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) { + verbose(8, "-- dstip wrong\n"); continue; + } } if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { - if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) + if (ip->ip_p != IPPROTO_UDP && + ip->ip_p != IPPROTO_TCP) { + verbose(8, "-- not port protocol\n"); continue; - if (tcp->th_dport != a->ac_dport) + } + if (tcp->th_dport != a->ac_dport) { + verbose(8, "-- dport mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_GROUP) != 0) { if (strncmp(a->ac_group, ipf->fl_group, - FR_GROUPLEN) != 0) + FR_GROUPLEN) != 0) { + verbose(8, "-- group mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { - if (strcmp(a->ac_iface, ipf->fl_ifname)) + if (strcmp(a->ac_iface, ipf->fl_ifname)) { + verbose(8, "-- ifname mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { - if (a->ac_proto != ip->ip_p) + if (a->ac_proto != ip->ip_p) { + verbose(8, "-- protocol mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_RESULT) != 0) { if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { - if (a->ac_result != IPMR_NOMATCH) + if (a->ac_result != IPMR_NOMATCH) { + verbose(8, "-- ff-flags mismatch\n"); continue; + } } else if (FR_ISPASS(ipf->fl_flags)) { - if (a->ac_result != IPMR_PASS) + if (a->ac_result != IPMR_PASS) { + verbose(8, "-- pass mismatch\n"); continue; + } } else if (FR_ISBLOCK(ipf->fl_flags)) { - if (a->ac_result != IPMR_BLOCK) + if (a->ac_result != IPMR_BLOCK) { + verbose(8, "-- block mismatch\n"); continue; + } } else { /* Log only */ - if (a->ac_result != IPMR_LOG) + if (a->ac_result != IPMR_LOG) { + verbose(8, "-- log mismatch\n"); continue; + } } } if ((a->ac_mflag & IPMAC_RULE) != 0) { - if (a->ac_rule != ipf->fl_rule) + if (a->ac_rule != ipf->fl_rule) { + verbose(8, "-- rule mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_SRCIP) != 0) { - if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) + if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) { + verbose(8, "-- srcip mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { - if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) + if (ip->ip_p != IPPROTO_UDP && + ip->ip_p != IPPROTO_TCP) { + verbose(8, "-- port protocol mismatch\n"); continue; - if (tcp->th_sport != a->ac_sport) + } + if (tcp->th_sport != a->ac_sport) { + verbose(8, "-- sport mismatch\n"); continue; + } } if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { - if (a->ac_logtag != ipf->fl_logtag) + if (a->ac_logtag != ipf->fl_logtag) { + verbose(8, "-- logtag %d != %d\n", + a->ac_logtag, ipf->fl_logtag); continue; + } } if ((a->ac_mflag & IPMAC_NATTAG) != 0) { if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, - IPFTAG_LEN) != 0) + IPFTAG_LEN) != 0) { + verbose(8, "-- nattag mismatch\n"); continue; + } } matched = 1; + verbose(8, "++ matched\n"); /* - * It matched so now execute the command + * It matched so now perform the saves */ - if (a->ac_syslog != 0) { - syslog(lvl, "%s", log); - } - - if (a->ac_savefp != NULL) { - if (a->ac_dflag & IPMDO_SAVERAW) - fwrite(ipl, 1, ipl->ipl_dsize, a->ac_savefp); - else - fputs(log, a->ac_savefp); - } - - if (a->ac_exec != NULL) { - switch (fork()) - { - case 0 : - { - FILE *pi; - - pi = popen(a->ac_run, "w"); - if (pi != NULL) { - fprintf(pi, "%s\n", log); - if ((opts & OPT_HEXHDR) != 0) { - dumphex(pi, 0, buf, - sizeof(*ipl) + - sizeof(*ipf)); - } - if ((opts & OPT_HEXBODY) != 0) { - dumphex(pi, 0, (char *)ip, - ipf->fl_hlen + - ipf->fl_plen); - } - pclose(pi); - } - exit(1); - } - case -1 : - break; - default : - break; - } - } + for (d = a->ac_doing; d != NULL; d = d->ipmd_next) + (*d->ipmd_store)(d->ipmd_token, &msg); } return matched; } -static void free_action(a) -ipmon_action_t *a; +static void +free_action(a) + ipmon_action_t *a; { - if (a->ac_savefile != NULL) { - free(a->ac_savefile); - a->ac_savefile = NULL; - } - if (a->ac_savefp != NULL) { - fclose(a->ac_savefp); - a->ac_savefp = NULL; - } - if (a->ac_exec != NULL) { - free(a->ac_exec); - if (a->ac_run == a->ac_exec) - a->ac_run = NULL; - a->ac_exec = NULL; - } - if (a->ac_run != NULL) { - free(a->ac_run); - a->ac_run = NULL; + ipmon_doing_t *d; + + while ((d = a->ac_doing) != NULL) { + a->ac_doing = d->ipmd_next; + (*d->ipmd_saver->ims_destroy)(d->ipmd_token); + free(d); } + if (a->ac_iface != NULL) { free(a->ac_iface); a->ac_iface = NULL; @@ -665,24 +650,21 @@ ipmon_action_t *a; } -int load_config(file) -char *file; +int +load_config(file) + char *file; { - ipmon_action_t *a; FILE *fp; char *s; + unload_config(); + s = getenv("YYDEBUG"); if (s != NULL) yydebug = atoi(s); else yydebug = 0; - while ((a = alist) != NULL) { - alist = a->ac_next; - free_action(a); - } - yylineNum = 1; (void) yysettab(yywords); @@ -698,3 +680,373 @@ char *file; fclose(fp); return 0; } + + +void +unload_config() +{ + ipmon_saver_int_t *sav, **imsip; + ipmon_saver_t *is; + ipmon_action_t *a; + + while ((a = alist) != NULL) { + alist = a->ac_next; + free_action(a); + } + + /* + * Look for savers that have been added in dynamically from the + * configuration file. + */ + for (imsip = &saverlist; (sav = *imsip) != NULL; ) { + if (sav->imsi_handle == NULL) + imsip = &sav->imsi_next; + else { + dlclose(sav->imsi_handle); + + *imsip = sav->imsi_next; + is = sav->imsi_stor; + free(sav); + + free(is->ims_name); + free(is); + } + } +} + + +void +dump_config() +{ + ipmon_action_t *a; + + for (a = alist; a != NULL; a = a->ac_next) { + print_action(a); + + printf("#\n"); + } +} + + +static void +print_action(a) + ipmon_action_t *a; +{ + ipmon_doing_t *d; + + printf("match { "); + print_match(a); + printf("; }\n"); + printf("do {"); + for (d = a->ac_doing; d != NULL; d = d->ipmd_next) { + printf("%s", d->ipmd_saver->ims_name); + if (d->ipmd_saver->ims_print != NULL) { + printf("(\""); + (*d->ipmd_saver->ims_print)(d->ipmd_token); + printf("\")"); + } + printf(";"); + } + printf("};\n"); +} + + +void * +add_doing(saver) + ipmon_saver_t *saver; +{ + ipmon_saver_int_t *it; + + if (find_doing(saver->ims_name) == IPM_DOING) + return NULL; + + it = calloc(1, sizeof(*it)); + if (it == NULL) + return NULL; + it->imsi_stor = saver; + it->imsi_next = saverlist; + saverlist = it; + return it; +} + + +static int +find_doing(string) + char *string; +{ + ipmon_saver_int_t *it; + + for (it = saverlist; it != NULL; it = it->imsi_next) { + if (!strcmp(it->imsi_stor->ims_name, string)) + return IPM_DOING; + } + return 0; +} + + +static ipmon_doing_t * +build_doing(target, options) + char *target; + char *options; +{ + ipmon_saver_int_t *it; + char *strarray[2]; + ipmon_doing_t *d, *d1; + ipmon_action_t *a; + ipmon_saver_t *save; + + d = calloc(1, sizeof(*d)); + if (d == NULL) + return NULL; + + for (it = saverlist; it != NULL; it = it->imsi_next) { + if (!strcmp(it->imsi_stor->ims_name, target)) + break; + } + if (it == NULL) { + free(d); + return NULL; + } + + strarray[0] = options; + strarray[1] = NULL; + + d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray); + if (d->ipmd_token == NULL) { + free(d); + return NULL; + } + + save = it->imsi_stor; + d->ipmd_saver = save; + d->ipmd_store = it->imsi_stor->ims_store; + + /* + * Look for duplicate do-things that need to be dup'd + */ + for (a = alist; a != NULL; a = a->ac_next) { + for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) { + if (save != d1->ipmd_saver) + continue; + if (save->ims_match == NULL || save->ims_dup == NULL) + continue; + if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token)) + continue; + + (*d->ipmd_saver->ims_destroy)(d->ipmd_token); + d->ipmd_token = (*save->ims_dup)(d1->ipmd_token); + break; + } + } + + return d; +} + + +static void +print_match(a) + ipmon_action_t *a; +{ + char *coma = ""; + + if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { + printf("direction = "); + if (a->ac_direction == IPM_IN) + printf("in"); + else if (a->ac_direction == IPM_OUT) + printf("out"); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_DSTIP) != 0) { + printf("%sdstip = ", coma); + printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { + printf("%sdstport = %hu", coma, ntohs(a->ac_dport)); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_GROUP) != 0) { + char group[FR_GROUPLEN+1]; + + strncpy(group, a->ac_group, FR_GROUPLEN); + group[FR_GROUPLEN] = '\0'; + printf("%sgroup = %s", coma, group); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { + printf("%siface = %s", coma, a->ac_iface); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { + printf("%slogtag = %u", coma, a->ac_logtag); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_NATTAG) != 0) { + char tag[17]; + + strncpy(tag, a->ac_nattag, 16); + tag[16] = '\0'; + printf("%snattag = %s", coma, tag); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { + printf("%sprotocol = %u", coma, a->ac_proto); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_RESULT) != 0) { + printf("%sresult = ", coma); + switch (a->ac_result) + { + case IPMR_LOG : + printf("log"); + break; + case IPMR_PASS : + printf("pass"); + break; + case IPMR_BLOCK : + printf("block"); + break; + case IPMR_NOMATCH : + printf("nomatch"); + break; + } + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_RULE) != 0) { + printf("%srule = %u", coma, a->ac_rule); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_EVERY) != 0) { + if (a->ac_packet > 1) { + printf("%severy %d packets", coma, a->ac_packet); + coma = ", "; + } else if (a->ac_packet == 1) { + printf("%severy packet", coma); + coma = ", "; + } + if (a->ac_second > 1) { + printf("%severy %d seconds", coma, a->ac_second); + coma = ", "; + } else if (a->ac_second == 1) { + printf("%severy second", coma); + coma = ", "; + } + } + + if ((a->ac_mflag & IPMAC_SRCIP) != 0) { + printf("%ssrcip = ", coma); + printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { + printf("%ssrcport = %hu", coma, ntohs(a->ac_sport)); + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_TYPE) != 0) { + printf("%stype = ", coma); + switch (a->ac_type) + { + case IPL_LOGIPF : + printf("ipf"); + break; + case IPL_LOGSTATE : + printf("state"); + break; + case IPL_LOGNAT : + printf("nat"); + break; + } + coma = ", "; + } + + if ((a->ac_mflag & IPMAC_WITH) != 0) { + printf("%swith ", coma); + coma = ", "; + } +} + + +static int +install_saver(name, path) + char *name, *path; +{ + ipmon_saver_int_t *isi; + ipmon_saver_t *is; + char nbuf[80]; + + if (find_doing(name) == IPM_DOING) + return -1; + + isi = calloc(1, sizeof(*isi)); + if (isi == NULL) + return -1; + + is = calloc(1, sizeof(*is)); + if (is == NULL) + goto loaderror; + + is->ims_name = name; + +#ifdef RTLD_LAZY + isi->imsi_handle = dlopen(path, RTLD_LAZY); +#endif +#ifdef DL_LAZY + isi->imsi_handle = dlopen(path, DL_LAZY); +#endif + + if (isi->imsi_handle == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sdup", name); + is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf); + + snprintf(nbuf, sizeof(nbuf), "%sdestroy", name); + is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_destroy == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%smatch", name); + is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf); + + snprintf(nbuf, sizeof(nbuf), "%sparse", name); + is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_parse == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sprint", name); + is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_print == NULL) + goto loaderror; + + snprintf(nbuf, sizeof(nbuf), "%sstore", name); + is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf); + if (is->ims_store == NULL) + goto loaderror; + + isi->imsi_stor = is; + isi->imsi_next = saverlist; + saverlist = isi; + + return 0; + +loaderror: + if (isi->imsi_handle != NULL) + dlclose(isi->imsi_handle); + free(isi); + if (is != NULL) + free(is); + return -1; +} diff --git a/contrib/ipfilter/tools/ipnat.c b/contrib/ipfilter/tools/ipnat.c index 28e29ec74199..448c1c0d2d2a 100644 --- a/contrib/ipfilter/tools/ipnat.c +++ b/contrib/ipfilter/tools/ipnat.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * @@ -67,7 +67,7 @@ extern char *sys_errlist[]; #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipnat.c,v 1.24.2.11 2007/09/25 08:27:34 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif @@ -79,23 +79,25 @@ char thishost[MAXHOSTNAMELEN]; extern char *optarg; -void dostats __P((int, natstat_t *, int, int)); -void dotable __P((natstat_t *, int, int)); -void flushtable __P((int, int)); +void dostats __P((int, natstat_t *, int, int, int *)); +void dotable __P((natstat_t *, int, int, int, char *)); +void flushtable __P((int, int, int *)); void usage __P((char *)); int main __P((int, char*[])); void showhostmap __P((natstat_t *nsp)); void natstat_dead __P((natstat_t *, char *)); -void dostats_live __P((int, natstat_t *, int)); +void dostats_live __P((int, natstat_t *, int, int *)); void showhostmap_dead __P((natstat_t *)); void showhostmap_live __P((int, natstat_t *)); -void dostats_dead __P((natstat_t *, int)); -void showtqtable_live __P((int)); +void dostats_dead __P((natstat_t *, int, int *)); +int nat_matcharray __P((nat_t *, int *)); -int opts; +int opts; +int nohdrfields = 0; +wordtab_t *nat_fields = NULL; void usage(name) -char *name; + char *name; { fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name); exit(1); @@ -103,12 +105,12 @@ char *name; int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { + int fd, c, mode, *natfilter; char *file, *core, *kernel; natstat_t ns, *nsp; - int fd, c, mode; ipfobj_t obj; fd = -1; @@ -118,8 +120,11 @@ char *argv[]; core = NULL; kernel = NULL; mode = O_RDWR; + natfilter = NULL; - while ((c = getopt(argc, argv, "CdFf:hlM:N:nrRsv")) != -1) + assigndefined(getenv("IPNAT_PREDEFINED")); + + while ((c = getopt(argc, argv, "CdFf:hlm:M:N:nO:prRsv")) != -1) switch (c) { case 'C' : @@ -141,6 +146,9 @@ char *argv[]; opts |= OPT_LIST; mode = O_RDONLY; break; + case 'm' : + natfilter = parseipfexpr(optarg, NULL); + break; case 'M' : core = optarg; break; @@ -148,9 +156,15 @@ char *argv[]; kernel = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; mode = O_RDONLY; break; + case 'O' : + nat_fields = parsefields(natfields, optarg); + break; + case 'p' : + opts |= OPT_PURGE; + break; case 'R' : opts |= OPT_NORESOLVE; break; @@ -168,6 +182,12 @@ char *argv[]; usage(argv[0]); } + if (((opts & OPT_PURGE) != 0) && ((opts & OPT_REMOVE) == 0)) { + (void) fprintf(stderr, "%s: -p must be used with -r\n", + argv[0]); + exit(1); + } + initparse(); if ((kernel != NULL) || (core != NULL)) { @@ -200,7 +220,7 @@ char *argv[]; obj.ipfo_size = sizeof(*nsp); obj.ipfo_ptr = (void *)nsp; if (ioctl(fd, SIOCGNATS, &obj) == -1) { - perror("ioctl(SIOCGNATS)"); + ipferror(fd, "ioctl(SIOCGNATS)"); exit(1); } (void) setgid(getgid()); @@ -211,17 +231,17 @@ char *argv[]; natstat_dead(nsp, kernel); if (opts & (OPT_LIST|OPT_STAT)) - dostats(fd, nsp, opts, 0); + dostats(fd, nsp, opts, 0, natfilter); exit(0); } if (opts & (OPT_FLUSH|OPT_CLEAR)) - flushtable(fd, opts); + flushtable(fd, opts, natfilter); if (file) { - ipnat_parsefile(fd, ipnat_addrule, ioctl, file); + return ipnat_parsefile(fd, ipnat_addrule, ioctl, file); } if (opts & (OPT_LIST|OPT_STAT)) - dostats(fd, nsp, opts, 1); + dostats(fd, nsp, opts, 1, natfilter); return 0; } @@ -231,8 +251,8 @@ char *argv[]; * rather than doing ioctl's. */ void natstat_dead(nsp, kernel) -natstat_t *nsp; -char *kernel; + natstat_t *nsp; + char *kernel; { struct nlist nat_nlist[10] = { { "nat_table" }, /* 0 */ @@ -243,7 +263,6 @@ char *kernel; { "ipf_rdrrules_sz" }, /* 5 */ { "ipf_hostmap_sz" }, { "nat_instances" }, - { "ap_sess_list" }, { NULL } }; void *tables[2]; @@ -259,8 +278,8 @@ char *kernel; * one in individually. */ kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables)); - nsp->ns_table[0] = tables[0]; - nsp->ns_table[1] = tables[1]; + nsp->ns_side[0].ns_table = tables[0]; + nsp->ns_side[1].ns_table = tables[1]; kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value, sizeof(nsp->ns_list)); @@ -276,8 +295,6 @@ char *kernel; sizeof(nsp->ns_hostmap_sz)); kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value, sizeof(nsp->ns_instances)); - kmemcpy((char *)&nsp->ns_apslist, nat_nlist[8].n_value, - sizeof(nsp->ns_apslist)); } @@ -285,23 +302,40 @@ char *kernel; * Issue an ioctl to flush either the NAT rules table or the active mapping * table or both. */ -void flushtable(fd, opts) -int fd, opts; +void flushtable(fd, opts, match) + int fd, opts, *match; { int n = 0; if (opts & OPT_FLUSH) { n = 0; - if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCFLNAT)"); - else + if (!(opts & OPT_DONOTHING)) { + if (match != NULL) { + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = match[0] * sizeof(int); + obj.ipfo_type = IPFOBJ_IPFEXPR; + obj.ipfo_ptr = match; + if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) { + ipferror(fd, "ioctl(SIOCMATCHFLUSH)"); + n = -1; + } else { + n = obj.ipfo_retval; + } + } else if (ioctl(fd, SIOCIPFFL, &n) == -1) { + ipferror(fd, "ioctl(SIOCIPFFL)"); + n = -1; + } + } + if (n >= 0) printf("%d entries flushed from NAT table\n", n); } if (opts & OPT_CLEAR) { n = 1; if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1) - perror("ioctl(SIOCCNATL)"); + ipferror(fd, "ioctl(SIOCCNATL)"); else printf("%d entries flushed from NAT list\n", n); } @@ -311,34 +345,65 @@ int fd, opts; /* * Display NAT statistics. */ -void dostats_dead(nsp, opts) -natstat_t *nsp; -int opts; +void dostats_dead(nsp, opts, filter) + natstat_t *nsp; + int opts, *filter; { nat_t *np, nat; ipnat_t ipn; + int i; - printf("List of active MAP/Redirect filters:\n"); - while (nsp->ns_list) { - if (kmemcpy((char *)&ipn, (long)nsp->ns_list, - sizeof(ipn))) { - perror("kmemcpy"); - break; + if (nat_fields == NULL) { + printf("List of active MAP/Redirect filters:\n"); + while (nsp->ns_list) { + if (kmemcpy((char *)&ipn, (long)nsp->ns_list, + sizeof(ipn))) { + perror("kmemcpy"); + break; + } + if (opts & OPT_HITS) + printf("%lu ", ipn.in_hits); + printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); + nsp->ns_list = ipn.in_next; } - if (opts & OPT_HITS) - printf("%lu ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; } - printf("\nList of active sessions:\n"); + if (nat_fields == NULL) { + printf("\nList of active sessions:\n"); + + } else if (nohdrfields == 0) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printfieldhdr(natfields, nat_fields + i); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } for (np = nsp->ns_instances; np; np = nat.nat_next) { if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) break; - printactivenat(&nat, opts, 0, nsp->ns_ticks); - if (nat.nat_aps) - printaps(nat.nat_aps, opts); + if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) + continue; + if (nat_fields != NULL) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printnatfield(&nat, nat_fields[i].w_value); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else { + printactivenat(&nat, opts, nsp->ns_ticks); + if (nat.nat_aps) { + int proto; + + if (nat.nat_dir & NAT_OUTBOUND) + proto = nat.nat_pr[1]; + else + proto = nat.nat_pr[0]; + printaps(nat.nat_aps, opts, proto); + } + } } if (opts & OPT_VERBOSE) @@ -346,62 +411,39 @@ int opts; } -void dostats(fd, nsp, opts, alive) -natstat_t *nsp; -int fd, opts, alive; -{ - /* - * Show statistics ? - */ - if (opts & OPT_STAT) { - printf("mapped\tin\t%lu\tout\t%lu\n", - nsp->ns_mapped[0], nsp->ns_mapped[1]); - printf("added\t%lu\texpired\t%lu\n", - nsp->ns_added, nsp->ns_expire); - printf("no memory\t%lu\tbad nat\t%lu\n", - nsp->ns_memfail, nsp->ns_badnat); - printf("inuse\t%lu\norphans\t%u\nrules\t%lu\n", - nsp->ns_inuse, nsp->ns_orphans, nsp->ns_rules); - printf("wilds\t%u\n", nsp->ns_wilds); - dotable(nsp, fd, alive); - if (opts & OPT_VERBOSE) - printf("table %p list %p\n", - nsp->ns_table, nsp->ns_list); - if (alive) - showtqtable_live(fd); - } - - if (opts & OPT_LIST) { - if (alive) - dostats_live(fd, nsp, opts); - else - dostats_dead(nsp, opts); - } -} - - -void dotable(nsp, fd, alive) -natstat_t *nsp; -int fd, alive; +void dotable(nsp, fd, alive, which, side) + natstat_t *nsp; + int fd, alive, which; + char *side; { - int sz, i, used, totallen, maxlen, minlen; + int sz, i, used, maxlen, minlen, totallen; ipftable_t table; - u_long *buckets; + u_int *buckets; ipfobj_t obj; sz = sizeof(*buckets) * nsp->ns_nattab_sz; - buckets = (u_long *)malloc(sz); + buckets = (u_int *)malloc(sz); + if (buckets == NULL) { + fprintf(stderr, + "cannot allocate memory (%d) for buckets\n", sz); + return; + } obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GTABLE; obj.ipfo_size = sizeof(table); obj.ipfo_ptr = &table; - table.ita_type = IPFTABLE_BUCKETS_NATIN; + if (which == 0) { + table.ita_type = IPFTABLE_BUCKETS_NATIN; + } else if (which == 1) { + table.ita_type = IPFTABLE_BUCKETS_NATOUT; + } table.ita_table = buckets; if (alive) { if (ioctl(fd, SIOCGTABL, &obj) != 0) { + ipferror(fd, "SIOCFTABL"); free(buckets); return; } @@ -412,9 +454,9 @@ int fd, alive; } } + minlen = nsp->ns_side[which].ns_inuse; totallen = 0; maxlen = 0; - minlen = nsp->ns_inuse; used = 0; for (i = 0; i < nsp->ns_nattab_sz; i++) { @@ -427,27 +469,84 @@ int fd, alive; totallen += buckets[i]; } - printf("hash efficiency\t%2.2f%%\n", - totallen ? ((float)used / totallen) * 100.0 : 0.0); - printf("bucket usage\t%2.2f%%\n", - ((float)used / nsp->ns_nattab_sz) * 100.0); - printf("minimal length\t%d\n", minlen); - printf("maximal length\t%d\n", maxlen); - printf("average length\t%.3f\n", used ? (float)totallen / used : 0.0); + printf("%d%%\thash efficiency %s\n", + totallen ? used * 100 / totallen : 0, side); + printf("%2.2f%%\tbucket usage %s\n", + ((float)used / nsp->ns_nattab_sz) * 100.0, side); + printf("%d\tminimal length %s\n", minlen, side); + printf("%d\tmaximal length %s\n", maxlen, side); + printf("%.3f\taverage length %s\n", + used ? ((float)totallen / used) : 0.0, side); + + free(buckets); +} + + +void dostats(fd, nsp, opts, alive, filter) + natstat_t *nsp; + int fd, opts, alive, *filter; +{ + /* + * Show statistics ? + */ + if (opts & OPT_STAT) { + printnatside("in", &nsp->ns_side[0]); + dotable(nsp, fd, alive, 0, "in"); + + printnatside("out", &nsp->ns_side[1]); + dotable(nsp, fd, alive, 1, "out"); + + printf("%lu\tlog successes\n", nsp->ns_side[0].ns_log); + printf("%lu\tlog failures\n", nsp->ns_side[1].ns_log); + printf("%lu\tadded in\n%lu\tadded out\n", + nsp->ns_side[0].ns_added, + nsp->ns_side[1].ns_added); + printf("%u\tactive\n", nsp->ns_active); + printf("%lu\ttransparent adds\n", nsp->ns_addtrpnt); + printf("%lu\tdivert build\n", nsp->ns_divert_build); + printf("%lu\texpired\n", nsp->ns_expire); + printf("%lu\tflush all\n", nsp->ns_flush_all); + printf("%lu\tflush closing\n", nsp->ns_flush_closing); + printf("%lu\tflush queue\n", nsp->ns_flush_queue); + printf("%lu\tflush state\n", nsp->ns_flush_state); + printf("%lu\tflush timeout\n", nsp->ns_flush_timeout); + printf("%lu\thostmap new\n", nsp->ns_hm_new); + printf("%lu\thostmap fails\n", nsp->ns_hm_newfail); + printf("%lu\thostmap add\n", nsp->ns_hm_addref); + printf("%lu\thostmap NULL rule\n", nsp->ns_hm_nullnp); + printf("%lu\tlog ok\n", nsp->ns_log_ok); + printf("%lu\tlog fail\n", nsp->ns_log_fail); + printf("%u\torphan count\n", nsp->ns_orphans); + printf("%u\trule count\n", nsp->ns_rules); + printf("%u\tmap rules\n", nsp->ns_rules_map); + printf("%u\trdr rules\n", nsp->ns_rules_rdr); + printf("%u\twilds\n", nsp->ns_wilds); + if (opts & OPT_VERBOSE) + printf("list %p\n", nsp->ns_list); + } + + if (opts & OPT_LIST) { + if (alive) + dostats_live(fd, nsp, opts, filter); + else + dostats_dead(nsp, opts, filter); + } } /* * Display NAT statistics. */ -void dostats_live(fd, nsp, opts) -natstat_t *nsp; -int fd, opts; +void dostats_live(fd, nsp, opts, filter) + natstat_t *nsp; + int fd, opts, *filter; { ipfgeniter_t iter; + char buffer[2000]; ipfobj_t obj; - ipnat_t ipn; + ipnat_t *ipn; nat_t nat; + int i; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; @@ -457,22 +556,39 @@ int fd, opts; iter.igi_type = IPFGENITER_IPNAT; iter.igi_nitems = 1; - iter.igi_data = &ipn; + iter.igi_data = buffer; + ipn = (ipnat_t *)buffer; /* * Show list of NAT rules and NAT sessions ? */ - printf("List of active MAP/Redirect filters:\n"); - while (nsp->ns_list) { - if (ioctl(fd, SIOCGENITER, &obj) == -1) - break; - if (opts & OPT_HITS) - printf("%lu ", ipn.in_hits); - printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); - nsp->ns_list = ipn.in_next; + if (nat_fields == NULL) { + printf("List of active MAP/Redirect filters:\n"); + while (nsp->ns_list) { + if (ioctl(fd, SIOCGENITER, &obj) == -1) + break; + if (opts & OPT_HITS) + printf("%lu ", ipn->in_hits); + printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE)); + nsp->ns_list = ipn->in_next; + } + } + + if (nat_fields == NULL) { + printf("\nList of active sessions:\n"); + + } else if (nohdrfields == 0) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printfieldhdr(natfields, nat_fields + i); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); } - printf("\nList of active sessions:\n"); + i = IPFGENITER_IPNAT; + (void) ioctl(fd,SIOCIPFDELTOK, &i); + iter.igi_type = IPFGENITER_NAT; iter.igi_nitems = 1; @@ -481,14 +597,35 @@ int fd, opts; while (nsp->ns_instances != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; - printactivenat(&nat, opts, 1, nsp->ns_ticks); - if (nat.nat_aps) - printaps(nat.nat_aps, opts); + if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0)) + continue; + if (nat_fields != NULL) { + for (i = 0; nat_fields[i].w_value != 0; i++) { + printnatfield(&nat, nat_fields[i].w_value); + if (nat_fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else { + printactivenat(&nat, opts, nsp->ns_ticks); + if (nat.nat_aps) { + int proto; + + if (nat.nat_dir & NAT_OUTBOUND) + proto = nat.nat_pr[1]; + else + proto = nat.nat_pr[0]; + printaps(nat.nat_aps, opts, proto); + } + } nsp->ns_instances = nat.nat_next; } if (opts & OPT_VERBOSE) showhostmap_live(fd, nsp); + + i = IPFGENITER_NAT; + (void) ioctl(fd,SIOCIPFDELTOK, &i); } @@ -496,7 +633,7 @@ int fd, opts; * Display the active host mapping table. */ void showhostmap_dead(nsp) -natstat_t *nsp; + natstat_t *nsp; { hostmap_t hm, *hmp, **maptable; u_int hv; @@ -532,12 +669,13 @@ natstat_t *nsp; * Display the active host mapping table. */ void showhostmap_live(fd, nsp) -int fd; -natstat_t *nsp; + int fd; + natstat_t *nsp; { ipfgeniter_t iter; hostmap_t hm; ipfobj_t obj; + int i; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; @@ -554,25 +692,167 @@ natstat_t *nsp; while (nsp->ns_maplist != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; - printhostmap(&hm, 0); + printhostmap(&hm, hm.hm_hv); nsp->ns_maplist = hm.hm_next; } + + i = IPFGENITER_HOSTMAP; + (void) ioctl(fd,SIOCIPFDELTOK, &i); } -void showtqtable_live(fd) -int fd; +int nat_matcharray(nat, array) + nat_t *nat; + int *array; { - ipftq_t table[IPF_TCP_NSTATES]; - ipfobj_t obj; + int i, n, *x, rv, p; + ipfexp_t *e; - bzero((char *)&obj, sizeof(obj)); - obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(table); - obj.ipfo_ptr = (void *)table; - obj.ipfo_type = IPFOBJ_STATETQTAB; + rv = 0; + n = array[0]; + x = array + 1; + + for (; n > 0; x += 3 + x[3], rv = 0) { + e = (ipfexp_t *)x; + if (e->ipfe_cmd == IPF_EXP_END) + break; + n -= e->ipfe_size; + + p = e->ipfe_cmd >> 16; + if ((p != 0) && (p != nat->nat_pr[1])) + break; + + switch (e->ipfe_cmd) + { + case IPF_EXP_IP_PR : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_pr[1] == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_IP_SRCADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_osrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_nsrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; - if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { - printtqtable(table); + case IPF_EXP_IP_DSTADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_odstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_ndstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + + case IPF_EXP_IP_ADDR : + if (nat->nat_v[0] != 4) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= ((nat->nat_osrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_nsrcaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_odstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]) || + ((nat->nat_ndstaddr & + e->ipfe_arg0[i * 2 + 1]) == + e->ipfe_arg0[i * 2]); + } + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_SRCADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_osrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_nsrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_DSTADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_odst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_ndst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; + + case IPF_EXP_IP6_ADDR : + if (nat->nat_v[0] != 6) + break; + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= IP6_MASKEQ(&nat->nat_osrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_nsrc6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_odst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]) || + IP6_MASKEQ(&nat->nat_ndst6, + &e->ipfe_arg0[i * 8 + 4], + &e->ipfe_arg0[i * 8]); + } + break; +#endif + + case IPF_EXP_UDP_PORT : + case IPF_EXP_TCP_PORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_osport == e->ipfe_arg0[i]) || + (nat->nat_nsport == e->ipfe_arg0[i]) || + (nat->nat_odport == e->ipfe_arg0[i]) || + (nat->nat_ndport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_SPORT : + case IPF_EXP_TCP_SPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_osport == e->ipfe_arg0[i]) || + (nat->nat_nsport == e->ipfe_arg0[i]); + } + break; + + case IPF_EXP_UDP_DPORT : + case IPF_EXP_TCP_DPORT : + for (i = 0; !rv && i < e->ipfe_narg; i++) { + rv |= (nat->nat_odport == e->ipfe_arg0[i]) || + (nat->nat_ndport == e->ipfe_arg0[i]); + } + break; + } + rv ^= e->ipfe_not; + + if (rv == 0) + break; } + + return rv; } diff --git a/contrib/ipfilter/tools/ipnat_y.y b/contrib/ipfilter/tools/ipnat_y.y index 7109f60ec710..71fb8ee37106 100644 --- a/contrib/ipfilter/tools/ipnat_y.y +++ b/contrib/ipfilter/tools/ipnat_y.y @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -60,33 +60,58 @@ static int natfd = -1; static ioctlfunc_t natioctlfunc = NULL; static addfunc_t nataddfunc = NULL; static int suggest_port = 0; +static proxyrule_t *prules = NULL; +static int parser_error = 0; static void newnatrule __P((void)); static void setnatproto __P((int)); - +static void setmapifnames __P((void)); +static void setrdrifnames __P((void)); +static void proxy_setconfig __P((int)); +static void proxy_unsetconfig __P((void)); +static namelist_t *proxy_dns_add_pass __P((char *, char *)); +static namelist_t *proxy_dns_add_block __P((char *, char *)); +static void proxy_addconfig __P((char *, int, char *, namelist_t *)); +static void proxy_loadconfig __P((int, ioctlfunc_t, char *, int, + char *, namelist_t *)); +static void proxy_loadrules __P((int, ioctlfunc_t, proxyrule_t *)); +static void setmapifnames __P((void)); +static void setrdrifnames __P((void)); +static void setifname __P((ipnat_t **, int, char *)); +static int addname __P((ipnat_t **, char *)); %} %union { char *str; u_32_t num; - struct in_addr ipa; + struct { + i6addr_t a; + int f; + } ipa; frentry_t fr; frtuc_t *frt; u_short port; struct { - u_short p1; - u_short p2; + int p1; + int p2; int pc; } pc; struct { - struct in_addr a; - struct in_addr m; + i6addr_t a; + i6addr_t m; + int t; /* Address type */ + int u; + int f; /* Family */ + int v; /* IP version */ + int s; /* 0 = number, 1 = text */ + int n; /* number */ } ipp; union i6addr ip6; + namelist_t *names; }; %token <num> YY_NUMBER YY_HEX %token <str> YY_STR -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 @@ -95,23 +120,42 @@ static void setnatproto __P((int)); %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG -%token IPNY_TLATE IPNY_SEQUENTIAL +%token IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO +%token IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT +%token IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6 +%token IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE %type <port> portspec %type <num> hexnumber compare range proto -%type <ipa> hostname ipv4 -%type <ipp> addr nummask rhaddr -%type <pc> portstuff +%type <num> saddr daddr sobject dobject mapfrom rdrfrom dip +%type <ipa> hostname ipv4 ipaddr +%type <ipp> addr rhsaddr rhdaddr erhdaddr +%type <pc> portstuff portpair comaports srcports dstports +%type <names> dnslines dnsline %% file: line | assign | file line | file assign + | file pconf ';' ; -line: xx rule { while ((nat = nattop) != NULL) { +line: xx rule { int err; + while ((nat = nattop) != NULL) { + if (nat->in_v[0] == 0) + nat->in_v[0] = 4; + if (nat->in_v[1] == 0) + nat->in_v[1] = nat->in_v[0]; nattop = nat->in_next; - (*nataddfunc)(natfd, natioctlfunc, nat); + err = (*nataddfunc)(natfd, natioctlfunc, nat); free(nat); + if (err != 0) { + parser_error = err; + break; + } + } + if (parser_error == 0 && prules != NULL) { + proxy_loadrules(natfd, natioctlfunc, prules); + prules = NULL; } resetlexer(); } @@ -136,206 +180,541 @@ xx: { newnatrule(); } rule: map eol | mapblock eol | redir eol + | rewrite ';' + | divert ';' + ; + +no: IPNY_NO { nat->in_flags |= IPN_NO; } ; eol: | ';' ; -map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); +map: mapit ifnames addr tlate rhsaddr proxy mapoptions + { if ($3.f != 0 && $3.f != $5.f && $5.f != 0) + yyerror("3.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); + } + | mapit ifnames addr tlate rhsaddr mapport mapoptions + { if ($3.f != $5.f && $3.f != 0 && $5.f != 0) + yyerror("4.address family mismatch"); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); + } + | no mapit ifnames addr setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = $4.v; + nat->in_osrcatype = $4.t; + bcopy(&$4.a, &nat->in_osrc.na_addr[0], + sizeof($4.a)); + bcopy(&$4.m, &nat->in_osrc.na_addr[1], + sizeof($4.a)); + + setmapifnames(); } - | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | mapit ifnames mapfrom tlate rhsaddr proxy mapoptions + { if ($3 != 0 && $5.f != 0 && $3 != $5.f) + yyerror("5.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3 != 0) + nat->in_v[0] = ftov($3); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3 != 0) + nat->in_v[1] = ftov($3); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } - | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions - { nat->in_v = 4; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | no mapit ifnames mapfrom setproto ';' + { nat->in_v[0] = ftov($4); + setmapifnames(); } - | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions - { nat->in_v = 4; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + | mapit ifnames mapfrom tlate rhsaddr mapport mapoptions + { if ($3 != 0 && $5.f != 0 && $3 != $5.f) + yyerror("6.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3 != 0) + nat->in_v[0] = ftov($3); + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3 != 0) + nat->in_v[1] = ftov($3); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } ; mapblock: - mapblockit ifnames addr IPNY_TLATE addr ports mapoptions - { nat->in_v = 4; - nat->in_inip = $3.a.s_addr; - nat->in_inmsk = $3.m.s_addr; - nat->in_outip = $5.a.s_addr; - nat->in_outmsk = $5.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_flags & IPN_TCPUDP) == 0) - setnatproto(nat->in_p); - if (((nat->in_redir & NAT_MAPBLK) != 0) || - ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) - nat_setgroupmap(nat); + mapblockit ifnames addr tlate addr ports mapoptions + { if ($3.f != 0 && $5.f != 0 && $3.f != $5.f) + yyerror("7.address family mismatch"); + if (nat->in_v[0] == 0 && $5.v != 0) + nat->in_v[0] = $5.v; + else if (nat->in_v[0] == 0 && $3.v != 0) + nat->in_v[0] = $3.v; + if (nat->in_v[1] == 0 && $5.v != 0) + nat->in_v[1] = $5.v; + else if (nat->in_v[1] == 0 && $3.v != 0) + nat->in_v[1] = $3.v; + nat->in_osrcatype = $3.t; + bcopy(&$3.a, &nat->in_osrc.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_osrc.na_addr[1], + sizeof($3.a)); + nat->in_nsrcatype = $5.t; + nat->in_nsrcafunc = $5.u; + bcopy(&$5.a, &nat->in_nsrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_nsrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); + } + | no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = $5.v; + if (nat->in_v[1] == 0) + nat->in_v[1] = $5.v; + nat->in_osrcatype = $5.t; + bcopy(&$5.a, &nat->in_osrc.na_addr[0], + sizeof($5.a)); + bcopy(&$5.m, &nat->in_osrc.na_addr[1], + sizeof($5.a)); + + setmapifnames(); } ; -redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions - { nat->in_v = 4; - nat->in_outip = $3.a.s_addr; - nat->in_outmsk = $3.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); - if ((nat->in_p == 0) && - ((nat->in_flags & IPN_TCPUDP) == 0) && - (nat->in_pmin != 0 || - nat->in_pmax != 0 || - nat->in_pnext != 0)) - setnatproto(IPPROTO_TCP); +redir: rdrit ifnames addr dport tlate dip nport setproto rdroptions + { if ($6 != 0 && $3.f != 0 && $6 != $3.f) + yyerror("21.address family mismatch"); + if (nat->in_v[0] == 0) { + if ($3.v != AF_UNSPEC) + nat->in_v[0] = ftov($3.f); + else + nat->in_v[0] = ftov($6); + } + nat->in_odstatype = $3.t; + bcopy(&$3.a, &nat->in_odst.na_addr[0], + sizeof($3.a)); + bcopy(&$3.m, &nat->in_odst.na_addr[1], + sizeof($3.a)); + + setrdrifnames(); } - | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions - { nat->in_v = 4; - if ((nat->in_p == 0) && - ((nat->in_flags & IPN_TCPUDP) == 0) && - (nat->in_pmin != 0 || - nat->in_pmax != 0 || - nat->in_pnext != 0)) - setnatproto(IPPROTO_TCP); - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + | no rdrit ifnames addr dport setproto ';' + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4.f); + nat->in_odstatype = $4.t; + bcopy(&$4.a, &nat->in_odst.na_addr[0], + sizeof($4.a)); + bcopy(&$4.m, &nat->in_odst.na_addr[1], + sizeof($4.a)); + + setrdrifnames(); } - | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions - { nat->in_v = 4; - nat->in_outip = $3.a.s_addr; - nat->in_outmsk = $3.m.s_addr; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + | rdrit ifnames rdrfrom tlate dip nport setproto rdroptions + { if ($5 != 0 && $3 != 0 && $5 != $3) + yyerror("20.address family mismatch"); + if (nat->in_v[0] == 0) { + if ($3 != AF_UNSPEC) + nat->in_v[0] = ftov($3); + else + nat->in_v[0] = ftov($5); + } + setrdrifnames(); + } + | no rdrit ifnames rdrfrom setproto ';' + { nat->in_v[0] = ftov($4); + + setrdrifnames(); } - | rdrit ifnames rdrfrom IPNY_TLATE dip setproto rdroptions - { nat->in_v = 4; - if ((suggest_port == 1) && - (nat->in_flags & IPN_TCPUDP) == 0) - nat->in_flags |= IPN_TCPUDP; - if (nat->in_ifnames[1][0] == '\0') - strncpy(nat->in_ifnames[1], - nat->in_ifnames[0], - sizeof(nat->in_ifnames[0])); + ; + +rewrite: + IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4); + if (nat->in_redir & NAT_MAP) + setmapifnames(); + else + setrdrifnames(); + nat->in_redir |= NAT_REWRITE; + } + ; + +divert: IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts + { if (nat->in_v[0] == 0) + nat->in_v[0] = ftov($4); + if (nat->in_redir & NAT_MAP) { + setmapifnames(); + nat->in_pr[0] = IPPROTO_UDP; + } else { + setrdrifnames(); + nat->in_pr[1] = IPPROTO_UDP; + } + nat->in_flags &= ~IPN_TCP; + } + ; + +tlate: IPNY_TLATE { yyexpectaddr = 1; } + ; + +pconf: IPNY_PROXY { yysetdict(proxies); } + IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{' + { proxy_setconfig(IPNY_DNS); } + dnslines ';' '}' + { proxy_addconfig("dns", $5, $7, $10); + proxy_unsetconfig(); + } + ; + +dnslines: + dnsline { $$ = $1; } + | dnslines ';' dnsline { $$ = $1; $1->na_next = $3; } + ; + +dnsline: + IPNY_ALLOW YY_STR { $$ = proxy_dns_add_pass(NULL, $2); } + | IPNY_DENY YY_STR { $$ = proxy_dns_add_block(NULL, $2); } + | IPNY_ALLOW '.' YY_STR { $$ = proxy_dns_add_pass(".", $3); } + | IPNY_DENY '.' YY_STR { $$ = proxy_dns_add_block(".", $3); } + ; + +oninout: + inout IPNY_ON ifnames { ; } + ; + +inout: IPNY_IN { nat->in_redir = NAT_REDIRECT; } + | IPNY_OUT { nat->in_redir = NAT_MAP; } + ; + +rwrproto: + | IPNY_PROTO setproto + ; + +newdst: src rhsaddr srcports dst erhdaddr dstports + { nat->in_nsrc.na_addr[0] = $2.a; + nat->in_nsrc.na_addr[1] = $2.m; + nat->in_nsrc.na_atype = $2.t; + if ($2.t == FRI_LOOKUP) { + nat->in_nsrc.na_type = $2.u; + nat->in_nsrc.na_subtype = $2.s; + nat->in_nsrc.na_num = $2.n; + } + nat->in_nsports[0] = $3.p1; + nat->in_nsports[1] = $3.p2; + nat->in_ndst.na_addr[0] = $5.a; + nat->in_ndst.na_addr[1] = $5.m; + nat->in_ndst.na_atype = $5.t; + if ($5.t == FRI_LOOKUP) { + nat->in_ndst.na_type = $5.u; + nat->in_ndst.na_subtype = $5.s; + nat->in_ndst.na_num = $5.n; + } + nat->in_ndports[0] = $6.p1; + nat->in_ndports[1] = $6.p2; + } + ; + +divdst: src addr ',' portspec dst addr ',' portspec IPNY_UDP + { nat->in_nsrc.na_addr[0] = $2.a; + if ($2.m.in4.s_addr != 0xffffffff) + yyerror("divert must have /32 dest"); + nat->in_nsrc.na_addr[1] = $2.m; + nat->in_nsports[0] = $4; + nat->in_nsports[1] = $4; + + nat->in_ndst.na_addr[0] = $6.a; + nat->in_ndst.na_addr[1] = $6.m; + if ($6.m.in4.s_addr != 0xffffffff) + yyerror("divert must have /32 dest"); + nat->in_ndports[0] = $8; + nat->in_ndports[1] = $8; + + nat->in_redir |= NAT_DIVERTUDP; + } + ; + +src: IPNY_SRC { yyexpectaddr = 1; } + ; + +dst: IPNY_DST { yyexpectaddr = 1; } + ; + +srcports: + comaports { $$.p1 = $1.p1; + $$.p2 = $1.p2; + } + | IPNY_PORT '=' portspec + { $$.p1 = $3; + $$.p2 = $3; + nat->in_flags |= IPN_FIXEDSPORT; + } + ; + +dstports: + comaports { $$.p1 = $1.p1; + $$.p2 = $1.p2; + } + | IPNY_PORT '=' portspec + { $$.p1 = $3; + $$.p2 = $3; + nat->in_flags |= IPN_FIXEDDPORT; + } + ; + +comaports: + { $$.p1 = 0; + $$.p2 = 0; + } + | ',' { if (!(nat->in_flags & IPN_TCPUDP)) + yyerror("must be TCP/UDP for ports"); + } + portpair { $$.p1 = $3.p1; + $$.p2 = $3.p2; } ; proxy: | IPNY_PROXY port portspec YY_STR '/' proto - { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); + { int pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; if (nat->in_dcmp == 0) { - nat->in_dport = htons($3); - } else if ($3 != nat->in_dport) { + nat->in_odport = $3; + } else if ($3 != nat->in_odport) { yyerror("proxy port numbers not consistant"); } + nat->in_ndport = $3; setnatproto($6); free($4); } | IPNY_PROXY port YY_STR YY_STR '/' proto - { int pnum; - strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); + { int pnum, pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; pnum = getportproto($3, $6); if (pnum == -1) yyerror("invalid port number"); - nat->in_dport = pnum; + nat->in_odport = ntohs(pnum); + nat->in_ndport = ntohs(pnum); setnatproto($6); free($3); free($4); } + | IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR + { int pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; + if (nat->in_dcmp == 0) { + nat->in_odport = $3; + } else if ($3 != nat->in_odport) { + yyerror("proxy port numbers not consistant"); + } + nat->in_ndport = $3; + setnatproto($6); + nat->in_pconfig = addname(&nat, $8); + free($4); + free($8); + } + | IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR + { int pnum, pos; + pos = addname(&nat, $4); + nat->in_plabel = pos; + pnum = getportproto($3, $6); + if (pnum == -1) + yyerror("invalid port number"); + nat->in_odport = ntohs(pnum); + nat->in_ndport = ntohs(pnum); + setnatproto($6); + pos = addname(&nat, $8); + nat->in_pconfig = pos; + free($3); + free($4); + free($8); + } ; - setproto: - | proto { if (nat->in_p != 0 || + | proto { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); setnatproto($1); } - | IPNY_TCPUDP { if (nat->in_p != 0 || + | IPNY_TCPUDP { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } - | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 || + | IPNY_TCP '/' IPNY_UDP { if (nat->in_pr[0] != 0 || + nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } ; -rhaddr: addr { $$.a = $1.a; $$.m = $1.m; } - | IPNY_RANGE ipv4 '-' ipv4 - { $$.a = $2; $$.m = $4; - nat->in_flags |= IPN_IPRANGE; } +rhsaddr: + addr { $$ = $1; + yyexpectaddr = 0; + } + | hostname '-' { yyexpectaddr = 1; } hostname + { $$.t = FRI_RANGE; + if ($1.f != $4.f) + yyerror("8.address family " + "mismatch"); + $$.f = $1.f; + $$.v = ftov($1.f); + $$.a = $1.a; + $$.m = $4.a; + nat->in_flags |= IPN_SIPRANGE; + yyexpectaddr = 0; + } + | IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname + { $$.t = FRI_RANGE; + if ($2.f != $5.f) + yyerror("9.address family " + "mismatch"); + $$.f = $2.f; + $$.v = ftov($2.f); + $$.a = $2.a; + $$.m = $5.a; + nat->in_flags |= IPN_SIPRANGE; + yyexpectaddr = 0; + } ; dip: - hostname { nat->in_inip = $1.s_addr; - nat->in_inmsk = 0xffffffff; } - | hostname '/' YY_NUMBER { if ($3 != 0 || $1.s_addr != 0) - yyerror("Only 0/0 supported"); - nat->in_inip = 0; - nat->in_inmsk = 0; + hostname ',' { yyexpectaddr = 1; } hostname + { nat->in_flags |= IPN_SPLIT; + if ($1.f != $4.f) + yyerror("10.address family " + "mismatch"); + $$ = $1.f; + nat->in_ndstip6 = $1.a; + nat->in_ndstmsk6 = $4.a; + nat->in_ndstatype = FRI_SPLIT; + yyexpectaddr = 0; + } + | rhdaddr { int bits; + nat->in_ndstip6 = $1.a; + nat->in_ndstmsk6 = $1.m; + nat->in_ndst.na_atype = $1.t; + yyexpectaddr = 0; + if ($1.f == AF_INET) + bits = count4bits($1.m.in4.s_addr); + else + bits = count6bits($1.m.i6); + if (($1.f == AF_INET) && (bits != 0) && + (bits != 32)) { + yyerror("dest ip bitmask not /32"); + } else if (($1.f == AF_INET6) && + (bits != 0) && (bits != 128)) { + yyerror("dest ip bitmask not /128"); + } + $$ = $1.f; + } + ; + +rhdaddr: + addr { $$ = $1; + yyexpectaddr = 0; + } + | hostname '-' hostname { bzero(&$$, sizeof($$)); + $$.t = FRI_RANGE; + if ($1.f != 0 && $3.f != 0 && + $1.f != $3.f) + yyerror("11.address family " + "mismatch"); + $$.a = $1.a; + $$.m = $3.a; + nat->in_flags |= IPN_DIPRANGE; + yyexpectaddr = 0; + } + | IPNY_RANGE hostname '-' hostname + { bzero(&$$, sizeof($$)); + $$.t = FRI_RANGE; + if ($2.f != 0 && $4.f != 0 && + $2.f != $4.f) + yyerror("12.address family " + "mismatch"); + $$.a = $2.a; + $$.m = $4.a; + nat->in_flags |= IPN_DIPRANGE; + yyexpectaddr = 0; + } + ; + +erhdaddr: + rhdaddr { $$ = $1; } + | IPNY_DSTLIST '/' YY_NUMBER { $$.t = FRI_LOOKUP; + $$.u = IPLT_DSTLIST; + $$.s = 0; + $$.n = $3; + } + | IPNY_DSTLIST '/' YY_STR { $$.t = FRI_LOOKUP; + $$.u = IPLT_DSTLIST; + $$.s = 1; + $$.n = addname(&nat, $3); } - | hostname ',' hostname { nat->in_flags |= IPN_SPLIT; - nat->in_inip = $1.s_addr; - nat->in_inmsk = $3.s_addr; } ; port: IPNY_PORT { suggest_port = 1; } @@ -347,27 +726,44 @@ portspec: else $$ = $1; } - | YY_STR { if (getport(NULL, $1, &($$)) == -1) + | YY_STR { if (getport(NULL, $1, + &($$), NULL) == -1) yyerror("invalid port number"); $$ = ntohs($$); } ; -dport: | port portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($2); } - | port portspec '-' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } - | port portspec ':' portspec { nat->in_pmin = htons($2); - nat->in_pmax = htons($4); } +portpair: + portspec { $$.p1 = $1; $$.p2 = $1; } + | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; } + | portspec ':' portspec { $$.p1 = $1; $$.p2 = $3; } ; -nport: port portspec { nat->in_pnext = htons($2); } - | port '=' portspec { nat->in_pnext = htons($3); +dport: | port portpair { nat->in_odport = $2.p1; + if ($2.p2 == 0) + nat->in_dtop = $2.p1; + else + nat->in_dtop = $2.p2; + } + ; + +nport: | port portpair { nat->in_dpmin = $2.p1; + nat->in_dpnext = $2.p1; + nat->in_dpmax = $2.p2; + nat->in_ndport = $2.p1; + if (nat->in_dtop == 0) + nat->in_dtop = $2.p2; + } + | port '=' portspec { nat->in_dpmin = $3; + nat->in_dpnext = $3; + nat->in_ndport = $3; + if (nat->in_dtop == 0) + nat->in_dtop = nat->in_odport; nat->in_flags |= IPN_FIXEDDPORT; } ; -ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; } +ports: | IPNY_PORTS YY_NUMBER { nat->in_spmin = $2; } | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } ; @@ -383,128 +779,282 @@ mapblockit: ; mapfrom: - from sobject IPNY_TO dobject - | from sobject '!' IPNY_TO dobject - { nat->in_flags |= IPN_NOTDST; } - | from sobject IPNY_TO '!' dobject - { nat->in_flags |= IPN_NOTDST; } + from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) + yyerror("13.address family " + "mismatch"); + $$ = $2; + } + | from sobject '!' to dobject + { if ($2 != 0 && $5 != 0 && $2 != $5) + yyerror("14.address family " + "mismatch"); + nat->in_flags |= IPN_NOTDST; + $$ = $2; + } + | from sobject to '!' dobject + { if ($2 != 0 && $5 != 0 && $2 != $5) + yyerror("15.address family " + "mismatch"); + nat->in_flags |= IPN_NOTDST; + $$ = $2; + } ; rdrfrom: - from sobject IPNY_TO dobject - | '!' from sobject IPNY_TO dobject - { nat->in_flags |= IPN_NOTSRC; } - | from '!' sobject IPNY_TO dobject - { nat->in_flags |= IPN_NOTSRC; } + from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) + yyerror("16.address family " + "mismatch"); + $$ = $2; + } + | '!' from sobject to dobject + { if ($3 != 0 && $5 != 0 && $3 != $5) + yyerror("17.address family " + "mismatch"); + nat->in_flags |= IPN_NOTSRC; + $$ = $3; + } + | from '!' sobject to dobject + { if ($3 != 0 && $5 != 0 && $3 != $5) + yyerror("18.address family " + "mismatch"); + nat->in_flags |= IPN_NOTSRC; + $$ = $3; + } ; -from: IPNY_FROM { nat->in_flags |= IPN_FILTER; } +from: IPNY_FROM { nat->in_flags |= IPN_FILTER; + yyexpectaddr = 1; + } + ; + +to: IPNY_TO { yyexpectaddr = 1; } ; ifnames: - ifname - | ifname ',' otherifname + ifname family { yyexpectaddr = 1; } + | ifname ',' otherifname family { yyexpectaddr = 1; } ; -ifname: YY_STR { strncpy(nat->in_ifnames[0], $1, - sizeof(nat->in_ifnames[0])); - nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; - free($1); - } +ifname: YY_STR { setifname(&nat, 0, $1); + free($1); + } + ; + +family: | IPNY_INET { nat->in_v[0] = 4; nat->in_v[1] = 4; } + | IPNY_INET6 { nat->in_v[0] = 6; nat->in_v[1] = 6; } ; otherifname: - YY_STR { strncpy(nat->in_ifnames[1], $1, - sizeof(nat->in_ifnames[1])); - nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; - free($1); - } + YY_STR { setifname(&nat, 1, $1); + free($1); + } ; mapport: - IPNY_PORTMAP tcpudp portspec ':' portspec randport - { nat->in_pmin = htons($3); - nat->in_pmax = htons($5); - } - | IPNY_PORTMAP tcpudp IPNY_AUTO randport - { nat->in_flags |= IPN_AUTOPORTMAP; - nat->in_pmin = htons(1024); - nat->in_pmax = htons(65535); - } - | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER - { if (strcmp($2, "icmp") != 0) { + IPNY_PORTMAP tcpudp portpair sequential + { nat->in_spmin = $3.p1; + nat->in_spmax = $3.p2; + } + | IPNY_PORTMAP portpair tcpudp sequential + { nat->in_spmin = $2.p1; + nat->in_spmax = $2.p2; + } + | IPNY_PORTMAP tcpudp IPNY_AUTO sequential + { nat->in_flags |= IPN_AUTOPORTMAP; + nat->in_spmin = 1024; + nat->in_spmax = 65535; + } + | IPNY_ICMPIDMAP YY_STR portpair sequential + { if (strcmp($2, "icmp") != 0 && + strcmp($2, "ipv6-icmp") != 0) { yyerror("icmpidmap not followed by icmp"); } free($2); - if ($3 < 0 || $3 > 65535) + if ($3.p1 < 0 || $3.p1 > 65535) yyerror("invalid ICMP Id number"); - if ($5 < 0 || $5 > 65535) + if ($3.p2 < 0 || $3.p2 > 65535) yyerror("invalid ICMP Id number"); + if (strcmp($2, "ipv6-icmp") == 0) { + nat->in_pr[0] = IPPROTO_ICMPV6; + nat->in_pr[1] = IPPROTO_ICMPV6; + } else { + nat->in_pr[0] = IPPROTO_ICMP; + nat->in_pr[1] = IPPROTO_ICMP; + } nat->in_flags = IPN_ICMPQUERY; - nat->in_pmin = htons($3); - nat->in_pmax = htons($5); + nat->in_spmin = $3.p1; + nat->in_spmax = $3.p2; } ; -randport: - | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; } - ; - sobject: - saddr - | saddr port portstuff { nat->in_sport = $3.p1; + saddr { $$ = $1; } + | saddr port portstuff { nat->in_osport = $3.p1; nat->in_stop = $3.p2; - nat->in_scmp = $3.pc; } + nat->in_scmp = $3.pc; + $$ = $1; + } ; -saddr: addr { if (nat->in_redir == NAT_REDIRECT) { - nat->in_srcip = $1.a.s_addr; - nat->in_srcmsk = $1.m.s_addr; - } else { - nat->in_inip = $1.a.s_addr; - nat->in_inmsk = $1.m.s_addr; - } +saddr: addr { nat->in_osrcatype = $1.t; + bcopy(&$1.a, + &nat->in_osrc.na_addr[0], + sizeof($1.a)); + bcopy(&$1.m, + &nat->in_osrc.na_addr[1], + sizeof($1.m)); + $$ = $1.f; } ; dobject: - daddr - | daddr port portstuff { nat->in_dport = $3.p1; + daddr { $$ = $1; } + | daddr port portstuff { nat->in_odport = $3.p1; nat->in_dtop = $3.p2; nat->in_dcmp = $3.pc; - if (nat->in_redir == NAT_REDIRECT) - nat->in_pmin = htons($3.p1); + $$ = $1; } ; -daddr: addr { if (nat->in_redir == NAT_REDIRECT) { - nat->in_outip = $1.a.s_addr; - nat->in_outmsk = $1.m.s_addr; - } else { - nat->in_srcip = $1.a.s_addr; - nat->in_srcmsk = $1.m.s_addr; +daddr: addr { nat->in_odstatype = $1.t; + bcopy(&$1.a, + &nat->in_odst.na_addr[0], + sizeof($1.a)); + bcopy(&$1.m, + &nat->in_odst.na_addr[1], + sizeof($1.m)); + $$ = $1.f; + } + ; + +addr: IPNY_ANY { yyexpectaddr = 0; + bzero(&$$, sizeof($$)); + $$.t = FRI_NORMAL; + } + | hostname { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.t = FRI_NORMAL; + $$.v = ftov($1.f); + $$.f = $1.f; + if ($$.f == AF_INET) { + $$.m.in4.s_addr = 0xffffffff; + } else if ($$.f == AF_INET6) { + $$.m.i6[0] = 0xffffffff; + $$.m.i6[1] = 0xffffffff; + $$.m.i6[2] = 0xffffffff; + $$.m.i6[3] = 0xffffffff; + } + yyexpectaddr = 0; + } + | hostname slash YY_NUMBER + { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.f = $1.f; + $$.v = ftov($1.f); + $$.t = FRI_NORMAL; + ntomask($$.f, $3, (u_32_t *)&$$.m); + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + yyexpectaddr = 0; + } + | hostname slash ipaddr { bzero(&$$, sizeof($$)); + if ($1.f != $3.f) { + yyerror("1.address family " + "mismatch"); + } + $$.a = $1.a; + $$.m = $3.a; + $$.t = FRI_NORMAL; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + yyexpectaddr = 0; + } + | hostname slash hexnumber { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.m.in4.s_addr = htonl($3); + $$.t = FRI_NORMAL; + $$.a.in4.s_addr &= $$.m.in4.s_addr; + $$.f = $1.f; + $$.v = ftov($1.f); + if ($$.f == AF_INET6) + yyerror("incorrect inet6 mask"); + } + | hostname mask ipaddr { bzero(&$$, sizeof($$)); + if ($1.f != $3.f) { + yyerror("2.address family " + "mismatch"); } + $$.a = $1.a; + $$.m = $3.a; + $$.t = FRI_NORMAL; + $$.a.i6[0] &= $$.m.i6[0]; + $$.a.i6[1] &= $$.m.i6[1]; + $$.a.i6[2] &= $$.m.i6[2]; + $$.a.i6[3] &= $$.m.i6[3]; + $$.f = $1.f; + $$.v = ftov($1.f); + yyexpectaddr = 0; + } + | hostname mask hexnumber { bzero(&$$, sizeof($$)); + $$.a = $1.a; + $$.m.in4.s_addr = htonl($3); + $$.t = FRI_NORMAL; + $$.a.in4.s_addr &= $$.m.in4.s_addr; + $$.f = AF_INET; + $$.v = 4; + } + | pool slash YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.iplookupnum = $3; + $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 0; + $$.t = FRI_LOOKUP; + } + | pool slash YY_STR { bzero(&$$, sizeof($$)); + $$.a.iplookupname = addname(&nat,$3); + $$.a.iplookuptype = IPLT_POOL; + $$.a.iplookupsubtype = 1; + $$.t = FRI_LOOKUP; + } + | hash slash YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.iplookupnum = $3; + $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 0; + $$.t = FRI_LOOKUP; + } + | hash slash YY_STR { bzero(&$$, sizeof($$)); + $$.a.iplookupname = addname(&nat,$3); + $$.a.iplookuptype = IPLT_HASH; + $$.a.iplookupsubtype = 1; + $$.t = FRI_LOOKUP; } ; -addr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; } - | nummask { $$.a = $1.a; $$.m = $1.m; - $$.a.s_addr &= $$.m.s_addr; } - | hostname '/' ipv4 { $$.a = $1; $$.m = $3; - $$.a.s_addr &= $$.m.s_addr; } - | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); - $$.a.s_addr &= $$.m.s_addr; } - | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3; - $$.a.s_addr &= $$.m.s_addr; } - | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); - $$.a.s_addr &= $$.m.s_addr; } +slash: '/' { yyexpectaddr = 0; } ; -nummask: - hostname { $$.a = $1; - $$.m.s_addr = 0xffffffff; } - | hostname '/' YY_NUMBER { $$.a = $1; - ntomask(4, $3, &$$.m.s_addr); } +mask: IPNY_MASK { yyexpectaddr = 0; } + ; + +pool: IPNY_POOL { if (!(nat->in_flags & IPN_FILTER)) { + yyerror("Can only use pool with from/to rules\n"); + } + yyexpectaddr = 0; + yyresetdict(); + } + ; + +hash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) { + yyerror("Can only use hash with from/to rules\n"); + } + yyexpectaddr = 0; + yyresetdict(); + } ; portstuff: @@ -513,17 +1063,16 @@ portstuff: ; mapoptions: - rr frag age mssclamp nattag setproto + rr frag age mssclamp nattag setproto purge ; rdroptions: - rr frag age sticky mssclamp rdrproxy nattag + rr frag age sticky mssclamp rdrproxy nattag purge ; nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, sizeof(nat->in_tag.ipt_tag)); } - rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; } ; @@ -536,9 +1085,9 @@ age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; nat->in_age[1] = $4; } ; -sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && +sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && !(nat->in_flags & IPN_SPLIT)) { - fprintf(stderr, + FPRINTF(stderr, "'sticky' for use with round-robin/IP splitting only\n"); } else nat->in_flags |= IPN_STICKY; @@ -549,30 +1098,47 @@ mssclamp: | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } ; -tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); } +tcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); } | IPNY_UDP { setnatproto(IPPROTO_UDP); } | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; - nat->in_p = 0; + nat->in_pr[0] = 0; + nat->in_pr[1] = 0; } ; +sequential: + | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; } + ; + +purge: + | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } + ; + rdrproxy: IPNY_PROXY YY_STR - { strncpy(nat->in_plabel, $2, - sizeof(nat->in_plabel)); - nat->in_dport = nat->in_pnext; - nat->in_dport = htons(nat->in_dport); + { int pos; + pos = addname(&nat, $2); + nat->in_plabel = pos; + nat->in_odport = nat->in_dpnext; + nat->in_dtop = nat->in_odport; free($2); } - | proxy { if (nat->in_plabel[0] != '\0') { - nat->in_pmin = nat->in_dport; - nat->in_pmax = nat->in_pmin; - nat->in_pnext = nat->in_pmin; - } - } + | proxy { if (nat->in_plabel != -1) { + nat->in_ndport = nat->in_odport; + nat->in_dpmin = nat->in_odport; + nat->in_dpmax = nat->in_dpmin; + nat->in_dtop = nat->in_dpmin; + nat->in_dpnext = nat->in_dpmin; + } + } + ; + +newopts: + | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } ; proto: YY_NUMBER { $$ = $1; @@ -582,7 +1148,10 @@ proto: YY_NUMBER { $$ = $1; } | IPNY_TCP { $$ = IPPROTO_TCP; } | IPNY_UDP { $$ = IPPROTO_UDP; } - | YY_STR { $$ = getproto($1); free($1); + | YY_STR { $$ = getproto($1); + free($1); + if ($$ == -1) + yyerror("unknwon protocol"); if ($$ != IPPROTO_TCP && $$ != IPPROTO_UDP) suggest_port = 0; @@ -594,14 +1163,39 @@ hexnumber: ; hostname: - YY_STR { if (gethost($1, &$$.s_addr) == -1) - fprintf(stderr, + YY_STR { i6addr_t addr; + + bzero(&$$, sizeof($$)); + if (gethost(AF_INET, $1, + &addr) == 0) { + $$.a = addr; + $$.f = AF_INET; + } else + if (gethost(AF_INET6, $1, + &addr) == 0) { + $$.a = addr; + $$.f = AF_INET6; + } else { + FPRINTF(stderr, "Unknown host '%s'\n", $1); + } free($1); } - | YY_NUMBER { $$.s_addr = htonl($1); } - | ipv4 { $$.s_addr = $1.s_addr; } + | YY_NUMBER { bzero(&$$, sizeof($$)); + $$.a.in4.s_addr = htonl($1); + if ($$.a.in4.s_addr != 0) + $$.f = AF_INET; + } + | ipv4 { $$ = $1; } + | YY_IPV6 { bzero(&$$, sizeof($$)); + $$.a = $1; + $$.f = AF_INET6; + } + | YY_NUMBER YY_IPV6 { bzero(&$$, sizeof($$)); + $$.a = $2; + $$.f = AF_INET6; + } ; compare: @@ -619,40 +1213,77 @@ range: | ':' { $$ = FR_INCRANGE; } ; +ipaddr: ipv4 { $$ = $1; } + | YY_IPV6 { $$.a = $1; + $$.f = AF_INET6; + } + ; + ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { yyerror("Invalid octet string for IP address"); return 0; } - $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; - $$.s_addr = htonl($$.s_addr); + bzero((char *)&$$, sizeof($$)); + $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; + $$.a.in4.s_addr = htonl($$.a.in4.s_addr); + $$.f = AF_INET; } ; %% +static wordtab_t proxies[] = { + { "dns", IPNY_DNS } +}; + +static wordtab_t dnswords[] = { + { "allow", IPNY_ALLOW }, + { "block", IPNY_DENY }, + { "deny", IPNY_DENY }, + { "drop", IPNY_DENY }, + { "pass", IPNY_ALLOW }, + +}; + static wordtab_t yywords[] = { { "age", IPNY_AGE }, { "any", IPNY_ANY }, { "auto", IPNY_AUTO }, { "bimap", IPNY_BIMAP }, + { "config", IPNY_CONFIG }, + { "divert", IPNY_DIVERT }, + { "dst", IPNY_DST }, + { "dstlist", IPNY_DSTLIST }, { "frag", IPNY_FRAG }, { "from", IPNY_FROM }, + { "hash", IPNY_HASH }, { "icmpidmap", IPNY_ICMPIDMAP }, + { "in", IPNY_IN }, + { "inet", IPNY_INET }, + { "inet6", IPNY_INET6 }, { "mask", IPNY_MASK }, { "map", IPNY_MAP }, { "map-block", IPNY_MAPBLOCK }, { "mssclamp", IPNY_MSSCLAMP }, { "netmask", IPNY_MASK }, + { "no", IPNY_NO }, + { "on", IPNY_ON }, + { "out", IPNY_OUT }, + { "pool", IPNY_POOL }, { "port", IPNY_PORT }, { "portmap", IPNY_PORTMAP }, { "ports", IPNY_PORTS }, + { "proto", IPNY_PROTO }, { "proxy", IPNY_PROXY }, + { "purge", IPNY_PURGE }, { "range", IPNY_RANGE }, + { "rewrite", IPNY_REWRITE }, { "rdr", IPNY_RDR }, { "round-robin",IPNY_ROUNDROBIN }, { "sequential", IPNY_SEQUENTIAL }, + { "src", IPNY_SRC }, { "sticky", IPNY_STICKY }, { "tag", IPNY_TAG }, { "tcp", IPNY_TCP }, @@ -671,15 +1302,19 @@ static wordtab_t yywords[] = { }; -int ipnat_parsefile(fd, addfunc, ioctlfunc, filename) -int fd; -addfunc_t addfunc; -ioctlfunc_t ioctlfunc; -char *filename; +int +ipnat_parsefile(fd, addfunc, ioctlfunc, filename) + int fd; + addfunc_t addfunc; + ioctlfunc_t ioctlfunc; + char *filename; { FILE *fp = NULL; + int rval; char *s; + yylineNum = 1; + (void) yysettab(yywords); s = getenv("YYDEBUG"); @@ -691,45 +1326,49 @@ char *filename; if (strcmp(filename, "-")) { fp = fopen(filename, "r"); if (!fp) { - fprintf(stderr, "fopen(%s) failed: %s\n", filename, + FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, STRERROR(errno)); return -1; } } else fp = stdin; - while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1) + while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) ; if (fp != NULL) fclose(fp); - return 0; + if (rval == -1) + rval = 0; + else if (rval != 0) + rval = 1; + return rval; } -int ipnat_parsesome(fd, addfunc, ioctlfunc, fp) -int fd; -addfunc_t addfunc; -ioctlfunc_t ioctlfunc; -FILE *fp; +int +ipnat_parsesome(fd, addfunc, ioctlfunc, fp) + int fd; + addfunc_t addfunc; + ioctlfunc_t ioctlfunc; + FILE *fp; { char *s; int i; - yylineNum = 1; - natfd = fd; + parser_error = 0; nataddfunc = addfunc; natioctlfunc = ioctlfunc; if (feof(fp)) - return 0; + return -1; i = fgetc(fp); if (i == EOF) - return 0; + return -1; if (ungetc(i, fp) == EOF) - return 0; + return -1; if (feof(fp)) - return 0; + return -1; s = getenv("YYDEBUG"); if (s) yydebug = atoi(s); @@ -738,11 +1377,12 @@ FILE *fp; yyin = fp; yyparse(); - return 1; + return parser_error; } -static void newnatrule() +static void +newnatrule() { ipnat_t *n; @@ -750,21 +1390,32 @@ static void newnatrule() if (n == NULL) return; - if (nat == NULL) + if (nat == NULL) { nattop = nat = n; - else { + n->in_pnext = &nattop; + } else { nat->in_next = n; + n->in_pnext = &nat->in_next; nat = n; } + n->in_flineno = yylineNum; + n->in_ifnames[0] = -1; + n->in_ifnames[1] = -1; + n->in_plabel = -1; + n->in_pconfig = -1; + n->in_size = sizeof(*n); + suggest_port = 0; } -static void setnatproto(p) -int p; +static void +setnatproto(p) + int p; { - nat->in_p = p; + nat->in_pr[0] = p; + nat->in_pr[1] = p; switch (p) { @@ -778,12 +1429,16 @@ int p; break; case IPPROTO_ICMP : nat->in_flags &= ~IPN_TCPUDP; - if (!(nat->in_flags & IPN_ICMPQUERY)) { + if (!(nat->in_flags & IPN_ICMPQUERY) && + !(nat->in_redir & NAT_DIVERTUDP)) { nat->in_dcmp = 0; nat->in_scmp = 0; - nat->in_pmin = 0; - nat->in_pmax = 0; - nat->in_pnext = 0; + nat->in_dpmin = 0; + nat->in_dpmax = 0; + nat->in_dpnext = 0; + nat->in_spmin = 0; + nat->in_spmax = 0; + nat->in_spnext = 0; } break; default : @@ -791,22 +1446,36 @@ int p; nat->in_flags &= ~IPN_TCPUDP; nat->in_dcmp = 0; nat->in_scmp = 0; - nat->in_pmin = 0; - nat->in_pmax = 0; - nat->in_pnext = 0; + nat->in_dpmin = 0; + nat->in_dpmax = 0; + nat->in_dpnext = 0; + nat->in_spmin = 0; + nat->in_spmax = 0; + nat->in_spnext = 0; } break; } + if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) { + nat->in_stop = 0; + nat->in_dtop = 0; + nat->in_osport = 0; + nat->in_odport = 0; + nat->in_stop = 0; + nat->in_osport = 0; + nat->in_dtop = 0; + nat->in_odport = 0; + } if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) nat->in_flags &= ~IPN_FIXEDDPORT; } -void ipnat_addrule(fd, ioctlfunc, ptr) -int fd; -ioctlfunc_t ioctlfunc; -void *ptr; +int +ipnat_addrule(fd, ioctlfunc, ptr) + int fd; + ioctlfunc_t ioctlfunc; + void *ptr; { ioctlcmd_t add, del; ipfobj_t obj; @@ -815,20 +1484,19 @@ void *ptr; ipn = ptr; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; - obj.ipfo_size = sizeof(ipnat_t); + obj.ipfo_size = ipn->in_size; obj.ipfo_type = IPFOBJ_IPNAT; obj.ipfo_ptr = ptr; - add = 0; - del = 0; if ((opts & OPT_DONOTHING) != 0) fd = -1; if (opts & OPT_ZERORULEST) { add = SIOCZRLST; - } else if (opts & OPT_INACTIVE) { - add = SIOCADNAT; - del = SIOCRMNAT; + del = 0; + } else if (opts & OPT_PURGE) { + add = 0; + del = SIOCPURGENAT; } else { add = SIOCADNAT; del = SIOCRMNAT; @@ -843,37 +1511,269 @@ void *ptr; if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(SIOCZRLST)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(zero nat rule)", + ipn->in_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } else { -#ifdef USE_QUAD_T -/* - printf("hits %qd bytes %qd ", - (long long)fr->fr_hits, - (long long)fr->fr_bytes); -*/ + PRINTF("hits %lu ", ipn->in_hits); +#ifdef USE_QUAD_T + PRINTF("bytes %"PRIu64" ", + ipn->in_bytes[0] + ipn->in_bytes[1]); #else -/* - printf("hits %ld bytes %ld ", - fr->fr_hits, fr->fr_bytes); -*/ + PRINTF("bytes %lu ", + ipn->in_bytes[0] + ipn->in_bytes[1]); #endif printnat(ipn, opts); } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(delete nat rule)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(delete nat rule)", + ipn->in_flineno); + return ipf_perror_fd(fd, ioctlfunc, msg); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { - fprintf(stderr, "%d:", yylineNum); - perror("ioctl(add/insert nat rule)"); + char msg[80]; + + sprintf(msg, "%d:ioctl(add/insert nat rule)", + ipn->in_flineno); + if (errno == EEXIST) { + sprintf(msg + strlen(msg), "(line %d)", + ipn->in_flineno); + } + return ipf_perror_fd(fd, ioctlfunc, msg); } } } + return 0; +} + + +static void +setmapifnames() +{ + if (nat->in_ifnames[1] == -1) + nat->in_ifnames[1] = nat->in_ifnames[0]; + + if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) + nat->in_flags |= IPN_TCPUDP; + + if ((nat->in_flags & IPN_TCPUDP) == 0) + setnatproto(nat->in_pr[1]); + + if (((nat->in_redir & NAT_MAPBLK) != 0) || + ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) + nat_setgroupmap(nat); +} + + +static void +setrdrifnames() +{ + if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) + nat->in_flags |= IPN_TCPUDP; + + if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && + (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0)) + setnatproto(IPPROTO_TCP); + + if (nat->in_ifnames[1] == -1) + nat->in_ifnames[1] = nat->in_ifnames[0]; +} + + +static void +proxy_setconfig(proxy) + int proxy; +{ + if (proxy == IPNY_DNS) { + yysetfixeddict(dnswords); + } +} + + +static void +proxy_unsetconfig() +{ + yyresetdict(); +} + + +static namelist_t * +proxy_dns_add_pass(prefix, name) + char *prefix, *name; +{ + namelist_t *n; + + n = calloc(1, sizeof(*n)); + if (n != NULL) { + if (prefix == NULL || *prefix == '\0') { + n->na_name = strdup(name); + } else { + n->na_name = malloc(strlen(name) + strlen(prefix) + 1); + strcpy(n->na_name, prefix); + strcat(n->na_name, name); + } + } + return n; +} + + +static namelist_t * +proxy_dns_add_block(prefix, name) + char *prefix, *name; +{ + namelist_t *n; + + n = calloc(1, sizeof(*n)); + if (n != NULL) { + if (prefix == NULL || *prefix == '\0') { + n->na_name = strdup(name); + } else { + n->na_name = malloc(strlen(name) + strlen(prefix) + 1); + strcpy(n->na_name, prefix); + strcat(n->na_name, name); + } + n->na_value = 1; + } + return n; +} + + +static void +proxy_addconfig(proxy, proto, conf, list) + char *proxy, *conf; + int proto; + namelist_t *list; +{ + proxyrule_t *pr; + + pr = calloc(1, sizeof(*pr)); + if (pr != NULL) { + pr->pr_proto = proto; + pr->pr_proxy = proxy; + pr->pr_conf = conf; + pr->pr_names = list; + pr->pr_next = prules; + prules = pr; + } +} + + +static void +proxy_loadrules(fd, ioctlfunc, rules) + int fd; + ioctlfunc_t ioctlfunc; + proxyrule_t *rules; +{ + proxyrule_t *pr; + + while ((pr = rules) != NULL) { + proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto, + pr->pr_conf, pr->pr_names); + rules = pr->pr_next; + free(pr->pr_conf); + free(pr); + } +} + + +static void +proxy_loadconfig(fd, ioctlfunc, proxy, proto, conf, list) + int fd; + ioctlfunc_t ioctlfunc; + char *proxy, *conf; + int proto; + namelist_t *list; +{ + namelist_t *na; + ipfobj_t obj; + ap_ctl_t pcmd; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_PROXYCTL; + obj.ipfo_size = sizeof(pcmd); + obj.ipfo_ptr = &pcmd; + + while ((na = list) != NULL) { + if ((opts & OPT_REMOVE) != 0) + pcmd.apc_cmd = APC_CMD_DEL; + else + pcmd.apc_cmd = APC_CMD_ADD; + pcmd.apc_dsize = strlen(na->na_name) + 1; + pcmd.apc_data = na->na_name; + pcmd.apc_arg = na->na_value; + pcmd.apc_p = proto; + + strncpy(pcmd.apc_label, proxy, APR_LABELLEN); + pcmd.apc_label[APR_LABELLEN - 1] = '\0'; + + strncpy(pcmd.apc_config, conf, APR_LABELLEN); + pcmd.apc_config[APR_LABELLEN - 1] = '\0'; + + if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) { + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + sprintf(msg, "%d:ioctl(add/remove proxy rule)", + yylineNum); + ipf_perror_fd(fd, ioctlfunc, msg); + return; + } + } + + list = na->na_next; + free(na->na_name); + free(na); + } +} + + +static void +setifname(np, idx, name) + ipnat_t **np; + int idx; + char *name; +{ + int pos; + + pos = addname(np, name); + if (pos == -1) + return; + (*np)->in_ifnames[idx] = pos; +} + + +static int +addname(np, name) + ipnat_t **np; + char *name; +{ + ipnat_t *n; + int nlen; + int pos; + + nlen = strlen(name) + 1; + n = realloc(*np, (*np)->in_size + nlen); + if (*np == nattop) + nattop = n; + *np = n; + if (n == NULL) + return -1; + if (n->in_pnext != NULL) + *n->in_pnext = n; + n->in_size += nlen; + pos = n->in_namelen; + n->in_namelen += nlen; + strcpy(n->in_names + pos, name); + n->in_names[n->in_namelen] = '\0'; + return pos; } diff --git a/contrib/ipfilter/tools/ippool.c b/contrib/ipfilter/tools/ippool.c index 8b7096050736..49cf7dae63d7 100644 --- a/contrib/ipfilter/tools/ippool.c +++ b/contrib/ipfilter/tools/ippool.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -61,41 +61,48 @@ int poolflush __P((int, char *[])); int poolstats __P((int, char *[])); int gettype __P((char *, u_int *)); int getrole __P((char *)); -int setnodeaddr __P((ip_pool_node_t *node, char *arg)); -void showpools_live __P((int, int, ip_pool_stat_t *, char *)); +int setnodeaddr __P((int, int, void *ptr, char *arg)); +void showpools_live __P((int, int, ipf_pool_stat_t *, char *)); void showhashs_live __P((int, int, iphtstat_t *, char *)); +void showdstls_live __P((int, int, ipf_dstl_stat_t *, char *)); int opts = 0; int fd = -1; int use_inet6 = 0; +wordtab_t *pool_fields = NULL; +int nohdrfields = 0; -void usage(prog) -char *prog; +void +usage(prog) + char *prog; { fprintf(stderr, "Usage:\t%s\n", prog); - fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n"); - fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n"); - fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); - fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); + fprintf(stderr, "\t-a [-dnv] [-m <name>] [-o <role>] [-t type] [-T ttl] -i <ipaddr>[/netmask]\n"); + fprintf(stderr, "\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n"); + fprintf(stderr, "\t-f <file> [-dnuv]\n"); + fprintf(stderr, "\t-F [-dv] [-o <role>] [-t <type>]\n"); + fprintf(stderr, "\t-l [-dv] [-m <name>] [-t <type>] [-O <fields>]\n"); + fprintf(stderr, "\t-r [-dnv] [-m <name>] [-o <role>] [-t type] -i <ipaddr>[/netmask]\n"); + fprintf(stderr, "\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n"); + fprintf(stderr, "\t-s [-dtv] [-M <core>] [-N <namelist>]\n"); exit(1); } -int main(argc, argv) -int argc; -char *argv[]; +int +main(argc, argv) + int argc; + char *argv[]; { - int err; + int err = 1; if (argc < 2) usage(argv[0]); - switch (getopt(argc, argv, "aAf:FlrRs")) + assigndefined(getenv("IPPOOL_PREDEFINED")); + + switch (getopt(argc, argv, "aAf:FlnrRsv")) { case 'a' : err = poolnodecommand(0, argc, argv); @@ -112,6 +119,9 @@ char *argv[]; case 'l' : err = poollist(argc, argv); break; + case 'n' : + opts |= OPT_DONOTHING|OPT_DONTOPEN; + break; case 'r' : err = poolnodecommand(1, argc, argv); break; @@ -121,6 +131,9 @@ char *argv[]; case 's' : err = poolstats(argc, argv); break; + case 'v' : + opts |= OPT_VERBOSE; + break; default : exit(1); } @@ -131,19 +144,23 @@ char *argv[]; } -int poolnodecommand(remove, argc, argv) -int remove, argc; -char *argv[]; +int +poolnodecommand(remove, argc, argv) + int remove, argc; + char *argv[]; { - int err, c, ipset, role; + int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0; char *poolname = NULL; - ip_pool_node_t node; + ip_pool_node_t pnode; + iphtent_t hnode; + void *ptr = &pnode; ipset = 0; role = IPL_LOGIPF; - bzero((char *)&node, sizeof(node)); + bzero((char *)&pnode, sizeof(pnode)); + bzero((char *)&hnode, sizeof(hnode)); - while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1) + while ((c = getopt(argc, argv, "di:m:no:Rt:T:v")) != -1) switch (c) { case 'd' : @@ -151,16 +168,21 @@ char *argv[]; ippool_yydebug++; break; case 'i' : - if (setnodeaddr(&node, optarg) == 0) + if (setnodeaddr(type, role, ptr, optarg) == 0) ipset = 1; break; case 'm' : poolname = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : + if (ipset == 1) { + fprintf(stderr, + "cannot set role after ip address\n"); + return -1; + } role = getrole(optarg); if (role == IPL_LOGNONE) return -1; @@ -168,13 +190,39 @@ char *argv[]; case 'R' : opts |= OPT_NORESOLVE; break; + case 't' : + if (ipset == 1) { + fprintf(stderr, + "cannot set type after ip address\n"); + return -1; + } + type = gettype(optarg, NULL); + switch (type) { + case IPLT_NONE : + fprintf(stderr, "unknown type '%s'\n", optarg); + return -1; + case IPLT_HASH : + ptr = &hnode; + break; + case IPLT_POOL : + default : + break; + } + break; + case 'T' : + ttl = atoi(optarg); + if (ttl < 0) { + fprintf(stderr, "cannot set negative ttl\n"); + return -1; + } + break; case 'v' : opts |= OPT_VERBOSE; break; } if (argv[optind] != NULL && ipset == 0) { - if (setnodeaddr(&node, argv[optind]) == 0) + if (setnodeaddr(type, role, ptr, argv[optind]) == 0) ipset = 1; } @@ -191,17 +239,30 @@ char *argv[]; return -1; } - if (remove == 0) - err = load_poolnode(0, poolname, &node, ioctl); - else - err = remove_poolnode(0, poolname, &node, ioctl); + switch (type) { + case IPLT_POOL : + if (remove == 0) + err = load_poolnode(role, poolname, &pnode, ttl, ioctl); + else + err = remove_poolnode(role, poolname, &pnode, ioctl); + break; + case IPLT_HASH : + if (remove == 0) + err = load_hashnode(role, poolname, &hnode, ttl, ioctl); + else + err = remove_hashnode(role, poolname, &hnode, ioctl); + break; + default : + break; + } return err; } -int poolcommand(remove, argc, argv) -int remove, argc; -char *argv[]; +int +poolcommand(remove, argc, argv) + int remove, argc; + char *argv[]; { int type, role, c, err; char *poolname; @@ -216,7 +277,7 @@ char *argv[]; bzero((char *)&iph, sizeof(iph)); bzero((char *)&pool, sizeof(pool)); - while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1) + while ((c = getopt(argc, argv, "dm:no:RSv")) != -1) switch (c) { case 'd' : @@ -227,7 +288,7 @@ char *argv[]; poolname = optarg; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : role = getrole(optarg); @@ -242,13 +303,6 @@ char *argv[]; case 'S' : iph.iph_seed = atoi(optarg); break; - case 't' : - type = gettype(optarg, &iph.iph_type); - if (type == IPLT_NONE) { - fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; - } - break; case 'v' : opts |= OPT_VERBOSE; break; @@ -262,6 +316,12 @@ char *argv[]; return -1; } + type = gettype(argv[optind], &iph.iph_type); + if (type == IPLT_NONE) { + fprintf(stderr, "unknown type '%s'\n", argv[optind]); + return -1; + } + if (type == IPLT_HASH) { strncpy(iph.iph_name, poolname, sizeof(iph.iph_name)); iph.iph_name[sizeof(iph.iph_name) - 1] = '\0'; @@ -297,9 +357,10 @@ char *argv[]; } -int loadpoolfile(argc, argv, infile) -int argc; -char *argv[], *infile; +int +loadpoolfile(argc, argv, infile) + int argc; + char *argv[], *infile; { int c; @@ -313,7 +374,7 @@ char *argv[], *infile; ippool_yydebug++; break; case 'n' : - opts |= OPT_DONOTHING; + opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'R' : opts |= OPT_NORESOLVE; @@ -329,7 +390,7 @@ char *argv[], *infile; if (opts & OPT_DEBUG) fprintf(stderr, "loadpoolfile: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -343,12 +404,14 @@ char *argv[], *infile; } -int poolstats(argc, argv) -int argc; -char *argv[]; +int +poolstats(argc, argv) + int argc; + char *argv[]; { int c, type, role, live_kernel; - ip_pool_stat_t plstat; + ipf_pool_stat_t plstat; + ipf_dstl_stat_t dlstat; char *kernel, *core; iphtstat_t htstat; iplookupop_t op; @@ -398,7 +461,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poolstats: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -410,14 +473,14 @@ char *argv[]; op.iplo_type = IPLT_POOL; op.iplo_struct = &plstat; op.iplo_size = sizeof(plstat); - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)"); return -1; } - printf("Pools:\t%lu\n", plstat.ipls_pools); - printf("Nodes:\t%lu\n", plstat.ipls_nodes); + printf("%lu\taddress pools\n", plstat.ipls_pools); + printf("%lu\taddress pool nodes\n", plstat.ipls_nodes); } } @@ -425,24 +488,49 @@ char *argv[]; op.iplo_type = IPLT_HASH; op.iplo_struct = &htstat; op.iplo_size = sizeof(htstat); - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return -1; + } + printf("%lu\thash tables\n", htstat.iphs_numtables); + printf("%lu\thash table nodes\n", htstat.iphs_numnodes); + printf("%lu\thash table no memory \n", + htstat.iphs_nomem); + } + } + + if (type == IPLT_ALL || type == IPLT_DSTLIST) { + op.iplo_type = IPLT_DSTLIST; + op.iplo_struct = &dlstat; + op.iplo_size = sizeof(dlstat); + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return -1; } - printf("Hash Tables:\t%lu\n", htstat.iphs_numtables); - printf("Nodes:\t%lu\n", htstat.iphs_numnodes); - printf("Out of Memory:\t%lu\n", htstat.iphs_nomem); + printf("%u\tdestination lists\n", + dlstat.ipls_numlists); + printf("%u\tdestination list nodes\n", + dlstat.ipls_numnodes); + printf("%lu\tdestination list no memory\n", + dlstat.ipls_nomem); + printf("%u\tdestination list zombies\n", + dlstat.ipls_numdereflists); + printf("%u\tdesetination list node zombies\n", + dlstat.ipls_numderefnodes); } } return 0; } -int poolflush(argc, argv) -int argc; -char *argv[]; +int +poolflush(argc, argv) + int argc; + char *argv[]; { int c, role, type, arg; iplookupflush_t flush; @@ -479,7 +567,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poolflush: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -492,22 +580,23 @@ char *argv[]; flush.iplf_unit = role; flush.iplf_arg = arg; - if (!(opts & OPT_DONOTHING)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) { - perror("ioctl(SIOCLOOKUPFLUSH)"); + ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)"); exit(1); } } - printf("%zd object%s flushed\n", flush.iplf_count, + printf("%u object%s flushed\n", flush.iplf_count, (flush.iplf_count == 1) ? "" : "s"); return 0; } -int getrole(rolename) -char *rolename; +int +getrole(rolename) + char *rolename; { int role; @@ -537,19 +626,20 @@ char *rolename; } -int gettype(typename, minor) -char *typename; -u_int *minor; +int +gettype(typename, minor) + char *typename; + u_int *minor; { int type; - if (!strcasecmp(optarg, "tree") || !strcasecmp(optarg, "pool")) { + if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) { type = IPLT_POOL; - } else if (!strcasecmp(optarg, "hash")) { + } else if (!strcasecmp(typename, "hash")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_LOOKUP; - } else if (!strcasecmp(optarg, "group-map")) { + } else if (!strcasecmp(typename, "group-map")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_GROUPMAP; @@ -560,9 +650,10 @@ u_int *minor; } -int poollist(argc, argv) -int argc; -char *argv[]; +int +poollist(argc, argv) + int argc; + char *argv[]; { char *kernel, *core, *poolname; int c, role, type, live_kernel; @@ -599,6 +690,9 @@ char *argv[]; return -1; } break; + case 'O' : + pool_fields = parsefields(poolfields, optarg); + break; case 'R' : opts |= OPT_NORESOLVE; break; @@ -617,7 +711,7 @@ char *argv[]; if (opts & OPT_DEBUG) fprintf(stderr, "poollist: opts = %#x\n", opts); - if (!(opts & OPT_DONOTHING) && (fd == -1)) { + if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); @@ -640,9 +734,10 @@ char *argv[]; } -void poollist_dead(role, poolname, type, kernel, core) -int role, type; -char *poolname, *kernel, *core; +void +poollist_dead(role, poolname, type, kernel, core) + int role, type; + char *poolname, *kernel, *core; { iphtable_t *hptr; ip_pool_t *ptr; @@ -665,14 +760,15 @@ char *poolname, *kernel, *core; ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, poolname, - opts); + opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, - poolname, opts); + poolname, opts, + pool_fields); } } role = IPL_LOGALL; @@ -693,14 +789,15 @@ char *poolname, *kernel, *core; hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, - poolname, opts); + poolname, opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, - poolname, opts); + poolname, opts, + pool_fields); } } } @@ -708,12 +805,12 @@ char *poolname, *kernel, *core; } -void poollist_live(role, poolname, type, fd) -int role, type, fd; -char *poolname; +void +poollist_live(role, poolname, type, fd) + int role, type, fd; + char *poolname; { - ip_pool_stat_t plstat; - iphtstat_t htstat; + ipf_pool_stat_t plstat; iplookupop_t op; int c; @@ -729,18 +826,18 @@ char *poolname; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showpools_live(fd, role, &plstat, poolname); } else { - for (role = 0; role <= IPL_LOGMAX; role++) { + for (role = -1; role <= IPL_LOGMAX; role++) { op.iplo_unit = role; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } @@ -752,6 +849,8 @@ char *poolname; } if (type == IPLT_ALL || type == IPLT_HASH) { + iphtstat_t htstat; + op.iplo_type = IPLT_HASH; op.iplo_size = sizeof(htstat); op.iplo_struct = &htstat; @@ -763,7 +862,7 @@ char *poolname; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showhashs_live(fd, role, &htstat, poolname); @@ -773,21 +872,57 @@ char *poolname; op.iplo_unit = role; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { - perror("ioctl(SIOCLOOKUPSTAT)"); + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showhashs_live(fd, role, &htstat, poolname); } + role = IPL_LOGALL; + } + } + + if (type == IPLT_ALL || type == IPLT_DSTLIST) { + ipf_dstl_stat_t dlstat; + + op.iplo_type = IPLT_DSTLIST; + op.iplo_size = sizeof(dlstat); + op.iplo_struct = &dlstat; + op.iplo_name[0] = '\0'; + op.iplo_arg = 0; + + if (role != IPL_LOGALL) { + op.iplo_unit = role; + + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return; + } + showdstls_live(fd, role, &dlstat, poolname); + } else { + for (role = 0; role <= IPL_LOGMAX; role++) { + + op.iplo_unit = role; + c = ioctl(fd, SIOCLOOKUPSTAT, &op); + if (c == -1) { + ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); + return; + } + + showdstls_live(fd, role, &dlstat, poolname); + } + role = IPL_LOGALL; } } } -void showpools_live(fd, role, plstp, poolname) -int fd, role; -ip_pool_stat_t *plstp; -char *poolname; +void +showpools_live(fd, role, plstp, poolname) + int fd, role; + ipf_pool_stat_t *plstp; + char *poolname; { ipflookupiter_t iter; ip_pool_t pool; @@ -806,22 +941,27 @@ char *poolname; iter.ili_unit = role; *iter.ili_name = '\0'; - while (plstp->ipls_list[role] != NULL) { + bzero((char *)&pool, sizeof(pool)); + + while (plstp->ipls_list[role + 1] != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { - perror("ioctl(SIOCLOOKUPITER)"); + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } - printpool_live(&pool, fd, poolname, opts); + if (((pool.ipo_flags & IPOOL_DELETE) == 0) || + ((opts & OPT_DEBUG) != 0)) + printpool_live(&pool, fd, poolname, opts, pool_fields); - plstp->ipls_list[role] = pool.ipo_next; + plstp->ipls_list[role + 1] = pool.ipo_next; } } -void showhashs_live(fd, role, htstp, poolname) -int fd, role; -iphtstat_t *htstp; -char *poolname; +void +showhashs_live(fd, role, htstp, poolname) + int fd, role; + iphtstat_t *htstp; + char *poolname; { ipflookupiter_t iter; iphtable_t table; @@ -842,18 +982,55 @@ char *poolname; while (htstp->iphs_tables != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { - perror("ioctl(SIOCLOOKUPITER)"); + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } - printhash_live(&table, fd, poolname, opts); + printhash_live(&table, fd, poolname, opts, pool_fields); htstp->iphs_tables = table.iph_next; } } -int setnodeaddr(ip_pool_node_t *node, char *arg) +void +showdstls_live(fd, role, dlstp, poolname) + int fd, role; + ipf_dstl_stat_t *dlstp; + char *poolname; +{ + ipflookupiter_t iter; + ippool_dst_t table; + ipfobj_t obj; + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_size = sizeof(iter); + obj.ipfo_ptr = &iter; + + iter.ili_type = IPLT_DSTLIST; + iter.ili_otype = IPFLOOKUPITER_LIST; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_nitems = 1; + iter.ili_data = &table; + iter.ili_unit = role; + *iter.ili_name = '\0'; + + while (dlstp->ipls_list[role] != NULL) { + if (ioctl(fd, SIOCLOOKUPITER, &obj)) { + ipferror(fd, "ioctl(SIOCLOOKUPITER)"); + break; + } + + printdstl_live(&table, fd, poolname, opts, pool_fields); + + dlstp->ipls_list[role] = table.ipld_next; + } +} + + +int +setnodeaddr(int type, int role, void *ptr, char *arg) { struct in_addr mask; char *s; @@ -862,17 +1039,38 @@ int setnodeaddr(ip_pool_node_t *node, char *arg) if (s == NULL) mask.s_addr = 0xffffffff; else if (strchr(s, '.') == NULL) { - if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0) + if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0) return -1; } else { mask.s_addr = inet_addr(s + 1); } if (s != NULL) *s = '\0'; - node->ipn_addr.adf_len = sizeof(node->ipn_addr); - node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); - node->ipn_mask.adf_len = sizeof(node->ipn_mask); - node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; + + if (type == IPLT_POOL) { + ip_pool_node_t *node = ptr; + + if (node->ipn_addr.adf_family == AF_INET) + node->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + + sizeof(struct in_addr); +#ifdef USE_INET6 + else + node->ipn_addr.adf_len = offsetof(addrfamily_t, + adf_addr) + + sizeof(struct in6_addr); +#endif + node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); + node->ipn_mask.adf_len = node->ipn_addr.adf_len; + node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr; + } else if (type == IPLT_HASH) { + iphtent_t *node = ptr; + + node->ipe_addr.in4.s_addr = inet_addr(arg); + node->ipe_mask.in4.s_addr = mask.s_addr; + node->ipe_family = AF_INET; + node->ipe_unit = role; + } return 0; } diff --git a/contrib/ipfilter/tools/ippool_y.y b/contrib/ipfilter/tools/ippool_y.y index 24f683bd1c19..34987452c65b 100644 --- a/contrib/ipfilter/tools/ippool_y.y +++ b/contrib/ipfilter/tools/ippool_y.y @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -35,6 +35,7 @@ #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" +#include "netinet/ip_dstlist.h" #include "ippool_l.h" #include "kmem.h" @@ -48,43 +49,52 @@ extern FILE *yyin; static iphtable_t ipht; static iphtent_t iphte; static ip_pool_t iplo; +static ippool_dst_t ipld; static ioctlfunc_t poolioctl = NULL; static char poolname[FR_GROUPLEN]; static iphtent_t *add_htablehosts __P((char *)); static ip_pool_node_t *add_poolhosts __P((char *)); +static ip_pool_node_t *read_whoisfile __P((char *)); +static void setadflen __P((addrfamily_t *)); %} %union { char *str; u_32_t num; - struct in_addr addr; + struct in_addr ip4; struct alist_s *alist; - struct in_addr adrmsk[2]; + addrfamily_t adrmsk[2]; iphtent_t *ipe; ip_pool_node_t *ipp; - union i6addr ip6; + ipf_dstnode_t *ipd; + addrfamily_t ipa; + i6addr_t ip6; } -%token <num> YY_NUMBER YY_HEX -%token <str> YY_STR -%token YY_COMMENT -%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT -%token YY_RANGE_OUT YY_RANGE_IN -%token <ip6> YY_IPV6 - -%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT -%token IPT_TABLE IPT_GROUPMAP IPT_HASH +%token <num> YY_NUMBER YY_HEX +%token <str> YY_STR +%token <ip6> YY_IPV6 +%token YY_COMMENT +%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT +%token YY_RANGE_OUT YY_RANGE_IN +%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT IPT_ALL +%token IPT_TABLE IPT_GROUPMAP IPT_HASH IPT_SRCHASH IPT_DSTHASH %token IPT_ROLE IPT_TYPE IPT_TREE -%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME -%type <num> role table inout +%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME IPT_POLICY +%token IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN +%token IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION +%token IPT_WHOIS IPT_FILE +%type <num> role table inout unit dstopts weighting %type <ipp> ipftree range addrlist %type <adrmsk> addrmask %type <ipe> ipfgroup ipfhash hashlist hashentry %type <ipe> groupentry setgrouplist grouplist -%type <addr> ipaddr mask ipv4 -%type <str> number setgroup +%type <ipa> ipaddr mask +%type <ip4> ipv4 +%type <str> number setgroup name +%type <ipd> dstentry dstentries dstlist %% file: line @@ -93,25 +103,44 @@ file: line | file assign ; -line: table role ipftree eol { iplo.ipo_unit = $2; +line: table role ipftree eol { ip_pool_node_t *n; + iplo.ipo_unit = $2; iplo.ipo_list = $3; load_pool(&iplo, poolioctl); + while ((n = $3) != NULL) { + $3 = n->ipn_next; + free(n); + } resetlexer(); + use_inet6 = 0; } - | table role ipfhash eol { ipht.iph_unit = $2; + | table role ipfhash eol { iphtent_t *h; + ipht.iph_unit = $2; ipht.iph_type = IPHASH_LOOKUP; load_hash(&ipht, $3, poolioctl); + while ((h = $3) != NULL) { + $3 = h->ipe_next; + free(h); + } resetlexer(); + use_inet6 = 0; } | groupmap role number ipfgroup eol - { ipht.iph_unit = $2; + { iphtent_t *h; + ipht.iph_unit = $2; strncpy(ipht.iph_name, $3, sizeof(ipht.iph_name)); ipht.iph_type = IPHASH_GROUPMAP; load_hash(&ipht, $4, poolioctl); + while ((h = $4) != NULL) { + $4 = h->ipe_next; + free(h); + } resetlexer(); + use_inet6 = 0; } | YY_COMMENT + | poolline eol ; eol: ';' @@ -132,6 +161,7 @@ assigning: table: IPT_TABLE { bzero((char *)&ipht, sizeof(ipht)); bzero((char *)&iphte, sizeof(iphte)); bzero((char *)&iplo, sizeof(iplo)); + bzero((char *)&ipld, sizeof(ipld)); *ipht.iph_name = '\0'; iplo.ipo_flags = IPHASH_ANON; iplo.ipo_name[0] = '\0'; @@ -150,11 +180,15 @@ groupmap: inout: IPT_IN { $$ = FR_INQUE; } | IPT_OUT { $$ = FR_OUTQUE; } ; -role: - IPT_ROLE '=' IPT_IPF { $$ = IPL_LOGIPF; } - | IPT_ROLE '=' IPT_NAT { $$ = IPL_LOGNAT; } - | IPT_ROLE '=' IPT_AUTH { $$ = IPL_LOGAUTH; } - | IPT_ROLE '=' IPT_COUNT { $$ = IPL_LOGCOUNT; } + +role: IPT_ROLE '=' unit { $$ = $3; } + ; + +unit: IPT_IPF { $$ = IPL_LOGIPF; } + | IPT_NAT { $$ = IPL_LOGNAT; } + | IPT_AUTH { $$ = IPL_LOGAUTH; } + | IPT_COUNT { $$ = IPL_LOGCOUNT; } + | IPT_ALL { $$ = IPL_LOGALL; } ; ipftree: @@ -183,14 +217,21 @@ ipfgroup: $1, FR_GROUPLEN); $$ = $4; + free($1); } - | hashopts start setgrouplist end { $$ = $3; } + | hashopts start setgrouplist end + { $$ = $3; } ; number: IPT_NUM '=' YY_NUMBER { sprintf(poolname, "%u", $3); $$ = poolname; } - | IPT_NAME '=' YY_STR { $$ = $3; } + | IPT_NAME '=' YY_STR { strncpy(poolname, $3, + FR_GROUPLEN); + poolname[FR_GROUPLEN-1]='\0'; + free($3); + $$ = poolname; + } | { $$ = ""; } ; @@ -198,6 +239,7 @@ setgroup: IPT_GROUP '=' YY_STR { char tmp[FR_GROUPLEN+1]; strncpy(tmp, $3, FR_GROUPLEN); $$ = strdup(tmp); + free($3); } | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1]; sprintf(tmp, "%u", $3); @@ -212,119 +254,162 @@ hashopts: ; addrlist: - next { $$ = NULL; } - | range next addrlist { $1->ipn_next = $3; $$ = $1; } + ';' { $$ = NULL; } + | range next addrlist { $$ = $1; + while ($1->ipn_next != NULL) + $1 = $1->ipn_next; + $1->ipn_next = $3; + } | range next { $$ = $1; } ; grouplist: - next { $$ = NULL; } + ';' { $$ = NULL; } | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; + $$->ipe_family = $1[0].adf_family; $$->ipe_next = $3; } | groupentry next { $$ = $1; } | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; +#ifdef AF_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; + } + | YY_STR { $$ = add_htablehosts($1); + free($1); } ; setgrouplist: - next { $$ = NULL; } + ';' { $$ = NULL; } | groupentry next { $$ = $1; } | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } ; groupentry: addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; strncpy($$->ipe_group, $3, FR_GROUPLEN); +#ifdef AF_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; free($3); } - | YY_STR { $$ = add_htablehosts($1); } ; -range: addrmask { $$ = calloc(1, sizeof(*$$)); - $$->ipn_info = 0; - $$->ipn_addr.adf_len = sizeof($$->ipn_addr); - $$->ipn_addr.adf_addr.in4.s_addr = $1[0].s_addr; - $$->ipn_mask.adf_len = sizeof($$->ipn_mask); - $$->ipn_mask.adf_addr.in4.s_addr = $1[1].s_addr; - } - | '!' addrmask { $$ = calloc(1, sizeof(*$$)); - $$->ipn_info = 1; - $$->ipn_addr.adf_len = sizeof($$->ipn_addr); - $$->ipn_addr.adf_addr.in4.s_addr = $2[0].s_addr; - $$->ipn_mask.adf_len = sizeof($$->ipn_mask); - $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr; - } - | YY_STR { $$ = add_poolhosts($1); } +range: addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 0; + $$->ipn_addr = $1[0]; + $$->ipn_mask = $1[1]; + } + | '!' addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 1; + $$->ipn_addr = $2[0]; + $$->ipn_mask = $2[1]; + } + | YY_STR { $$ = add_poolhosts($1); + free($1); + } + | IPT_WHOIS IPT_FILE YY_STR { $$ = read_whoisfile($3); + free($3); + } + ; hashlist: - next { $$ = NULL; } + ';' { $$ = NULL; } | hashentry next { $$ = $1; } | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } ; hashentry: - addrmask { $$ = calloc(1, sizeof(iphtent_t)); - bcopy((char *)&($1[0]), - (char *)&($$->ipe_addr), - sizeof($$->ipe_addr)); - bcopy((char *)&($1[1]), - (char *)&($$->ipe_mask), - sizeof($$->ipe_mask)); - } - | YY_STR { $$ = add_htablehosts($1); } + addrmask { $$ = calloc(1, sizeof(iphtent_t)); + $$->ipe_addr = $1[0].adf_addr; + $$->ipe_mask = $1[1].adf_addr; +#ifdef USE_INET6 + if (use_inet6) + $$->ipe_family = AF_INET6; + else +#endif + $$->ipe_family = AF_INET; + } + | YY_STR { $$ = add_htablehosts($1); + free($1); + } ; addrmask: - ipaddr '/' mask { $$[0] = $1; $$[1].s_addr = $3.s_addr; - yyexpectaddr = 0; + ipaddr '/' mask { $$[0] = $1; + setadflen(&$$[0]); + $$[1] = $3; + $$[1].adf_len = $$[0].adf_len; } - | ipaddr { $$[0] = $1; $$[1].s_addr = 0xffffffff; - yyexpectaddr = 0; + | ipaddr { $$[0] = $1; + setadflen(&$$[1]); + $$[1].adf_len = $$[0].adf_len; +#ifdef USE_INET6 + if (use_inet6) + memset(&$$[1].adf_addr, 0xff, + sizeof($$[1].adf_addr.in6)); + else +#endif + memset(&$$[1].adf_addr, 0xff, + sizeof($$[1].adf_addr.in4)); } ; -ipaddr: ipv4 { $$ = $1; } - | YY_NUMBER { $$.s_addr = htonl($1); } - ; - -mask: YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$.s_addr); } - | ipv4 { $$ = $1; } - ; - -start: '{' { yyexpectaddr = 1; } - ; - -end: '}' { yyexpectaddr = 0; } +ipaddr: ipv4 { $$.adf_addr.in4 = $1; + $$.adf_family = AF_INET; + setadflen(&$$); + use_inet6 = 0; + } + | YY_NUMBER { $$.adf_addr.in4.s_addr = htonl($1); + $$.adf_family = AF_INET; + setadflen(&$$); + use_inet6 = 0; + } + | YY_IPV6 { $$.adf_addr = $1; + $$.adf_family = AF_INET6; + setadflen(&$$); + use_inet6 = 1; + } ; -next: ';' { yyexpectaddr = 1; } +mask: YY_NUMBER { bzero(&$$, sizeof($$)); + if (use_inet6) { + if (ntomask(AF_INET6, $1, + (u_32_t *)&$$.adf_addr) == -1) + yyerror("bad bitmask"); + } else { + if (ntomask(AF_INET, $1, + (u_32_t *)&$$.adf_addr.in4) == -1) + yyerror("bad bitmask"); + } + } + | ipv4 { bzero(&$$, sizeof($$)); + $$.adf_addr.in4 = $1; + } + | YY_IPV6 { bzero(&$$, sizeof($$)); + $$.adf_addr = $1; + } ; -size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } +size: IPT_SIZE '=' YY_NUMBER { ipht.iph_size = $3; } ; -seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } +seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } ; ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER @@ -336,26 +421,180 @@ ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER $$.s_addr = htonl($$.s_addr); } ; + +next: ';' { yyexpectaddr = 1; } + ; + +start: '{' { yyexpectaddr = 1; } + ; + +end: '}' { yyexpectaddr = 0; } + ; + +poolline: + IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')' + start dstlist end + { bzero((char *)&ipld, sizeof(ipld)); + strncpy(ipld.ipld_name, $6, + sizeof(ipld.ipld_name)); + ipld.ipld_unit = $2; + ipld.ipld_policy = $8; + load_dstlist(&ipld, poolioctl, $11); + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_POOL unit '/' IPT_TREE '(' name ';' ')' + start addrlist end + { bzero((char *)&iplo, sizeof(iplo)); + strncpy(iplo.ipo_name, $6, + sizeof(iplo.ipo_name)); + iplo.ipo_list = $10; + iplo.ipo_unit = $2; + load_pool(&iplo, poolioctl); + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_POOL '(' name ';' ')' start addrlist end + { bzero((char *)&iplo, sizeof(iplo)); + strncpy(iplo.ipo_name, $3, + sizeof(iplo.ipo_name)); + iplo.ipo_list = $7; + iplo.ipo_unit = IPL_LOGALL; + load_pool(&iplo, poolioctl); + resetlexer(); + use_inet6 = 0; + free($3); + } + | IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')' + start hashlist end + { iphtent_t *h; + bzero((char *)&ipht, sizeof(ipht)); + strncpy(ipht.iph_name, $6, + sizeof(ipht.iph_name)); + ipht.iph_unit = $2; + load_hash(&ipht, $11, poolioctl); + while ((h = ipht.iph_list) != NULL) { + ipht.iph_list = h->ipe_next; + free(h); + } + resetlexer(); + use_inet6 = 0; + free($6); + } + | IPT_GROUPMAP '(' name ';' inout ';' ')' + start setgrouplist end + { iphtent_t *h; + bzero((char *)&ipht, sizeof(ipht)); + strncpy(ipht.iph_name, $3, + sizeof(ipht.iph_name)); + ipht.iph_type = IPHASH_GROUPMAP; + ipht.iph_unit = IPL_LOGIPF; + ipht.iph_flags = $5; + load_hash(&ipht, $9, poolioctl); + while ((h = ipht.iph_list) != NULL) { + ipht.iph_list = h->ipe_next; + free(h); + } + resetlexer(); + use_inet6 = 0; + free($3); + } + ; + +name: IPT_NAME YY_STR { $$ = $2; } + | IPT_NUM YY_NUMBER { char name[80]; + sprintf(name, "%d", $2); + $$ = strdup(name); + } + ; + +hashoptlist: + | hashopt ';' + | hashoptlist ';' hashopt ';' + ; +hashopt: + IPT_SIZE YY_NUMBER + | IPT_SEED YY_NUMBER + ; + +dstlist: + dstentries { $$ = $1; } + | ';' { $$ = NULL; } + ; + +dstentries: + dstentry next { $$ = $1; } + | dstentry next dstentries { $1->ipfd_next = $3; $$ = $1; } + ; + +dstentry: + YY_STR ':' ipaddr { int size = sizeof(*$$) + strlen($1) + 1; + $$ = calloc(1, size); + if ($$ != NULL) { + $$->ipfd_dest.fd_name = strlen($1) + 1; + bcopy($1, $$->ipfd_names, + $$->ipfd_dest.fd_name); + $$->ipfd_dest.fd_addr = $3; + $$->ipfd_size = size; + } + free($1); + } + | ipaddr { $$ = calloc(1, sizeof(*$$)); + if ($$ != NULL) { + $$->ipfd_dest.fd_name = -1; + $$->ipfd_dest.fd_addr = $1; + $$->ipfd_size = sizeof(*$$); + } + } + ; + +dstopts: + { $$ = IPLDP_NONE; } + | IPT_POLICY IPT_ROUNDROBIN ';' { $$ = IPLDP_ROUNDROBIN; } + | IPT_POLICY IPT_WEIGHTED weighting ';' { $$ = $3; } + | IPT_POLICY IPT_RANDOM ';' { $$ = IPLDP_RANDOM; } + | IPT_POLICY IPT_HASH ';' { $$ = IPLDP_HASHED; } + | IPT_POLICY IPT_SRCHASH ';' { $$ = IPLDP_SRCHASH; } + | IPT_POLICY IPT_DSTHASH ';' { $$ = IPLDP_DSTHASH; } + ; + +weighting: + IPT_CONNECTION { $$ = IPLDP_CONNECTION; } + ; %% static wordtab_t yywords[] = { - { "auth", IPT_AUTH }, - { "count", IPT_COUNT }, - { "group", IPT_GROUP }, - { "group-map", IPT_GROUPMAP }, - { "hash", IPT_HASH }, - { "in", IPT_IN }, - { "ipf", IPT_IPF }, - { "name", IPT_NAME }, - { "nat", IPT_NAT }, - { "number", IPT_NUM }, - { "out", IPT_OUT }, - { "role", IPT_ROLE }, - { "seed", IPT_SEED }, - { "size", IPT_SIZE }, - { "table", IPT_TABLE }, - { "tree", IPT_TREE }, - { "type", IPT_TYPE }, - { NULL, 0 } + { "all", IPT_ALL }, + { "auth", IPT_AUTH }, + { "connection", IPT_CONNECTION }, + { "count", IPT_COUNT }, + { "dst-hash", IPT_DSTHASH }, + { "dstlist", IPT_DSTLIST }, + { "file", IPT_FILE }, + { "group", IPT_GROUP }, + { "group-map", IPT_GROUPMAP }, + { "hash", IPT_HASH }, + { "in", IPT_IN }, + { "ipf", IPT_IPF }, + { "name", IPT_NAME }, + { "nat", IPT_NAT }, + { "number", IPT_NUM }, + { "out", IPT_OUT }, + { "policy", IPT_POLICY }, + { "pool", IPT_POOL }, + { "random", IPT_RANDOM }, + { "round-robin", IPT_ROUNDROBIN }, + { "role", IPT_ROLE }, + { "seed", IPT_SEED }, + { "size", IPT_SIZE }, + { "src-hash", IPT_SRCHASH }, + { "table", IPT_TABLE }, + { "tree", IPT_TREE }, + { "type", IPT_TYPE }, + { "weighted", IPT_WEIGHTED }, + { "whois", IPT_WHOIS }, + { NULL, 0 } }; @@ -441,8 +680,9 @@ char *url; if (hlist == NULL) return NULL; - if (gethost(url, &hlist->al_addr) == -1) + if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); + } } hbot = NULL; @@ -453,10 +693,9 @@ char *url; if (h == NULL) break; - bcopy((char *)&a->al_addr, (char *)&h->ipe_addr, - sizeof(h->ipe_addr)); - bcopy((char *)&a->al_mask, (char *)&h->ipe_mask, - sizeof(h->ipe_mask)); + h->ipe_family = a->al_family; + h->ipe_addr = a->al_i6addr; + h->ipe_mask = a->al_i6mask; if (hbot != NULL) hbot->ipe_next = h; @@ -487,8 +726,9 @@ char *url; if (hlist == NULL) return NULL; - if (gethost(url, &hlist->al_addr) == -1) + if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); + } } pbot = NULL; @@ -498,16 +738,19 @@ char *url; p = calloc(1, sizeof(*p)); if (p == NULL) break; + p->ipn_mask.adf_addr = a->al_i6mask; - p->ipn_addr.adf_len = 8; - p->ipn_mask.adf_len = 8; - + if (a->al_family == AF_INET) { + p->ipn_addr.adf_family = AF_INET; +#ifdef USE_INET6 + } else if (a->al_family == AF_INET6) { + p->ipn_addr.adf_family = AF_INET6; +#endif + } + setadflen(&p->ipn_addr); + p->ipn_addr.adf_addr = a->al_i6addr; p->ipn_info = a->al_not; - - bcopy((char *)&a->al_addr, (char *)&p->ipn_addr.adf_addr, - sizeof(p->ipn_addr.adf_addr)); - bcopy((char *)&a->al_mask, (char *)&p->ipn_mask.adf_addr, - sizeof(p->ipn_mask.adf_addr)); + p->ipn_mask.adf_len = p->ipn_addr.adf_len; if (pbot != NULL) pbot->ipn_next = p; @@ -520,3 +763,59 @@ char *url; return ptop; } + + +ip_pool_node_t * +read_whoisfile(file) + char *file; +{ + ip_pool_node_t *ntop, *ipn, node, *last; + char line[1024]; + FILE *fp; + + fp = fopen(file, "r"); + if (fp == NULL) + return NULL; + + last = NULL; + ntop = NULL; + while (fgets(line, sizeof(line) - 1, fp) != NULL) { + line[sizeof(line) - 1] = '\0'; + + if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask)) + continue; + ipn = calloc(1, sizeof(*ipn)); + if (ipn == NULL) + continue; + ipn->ipn_addr = node.ipn_addr; + ipn->ipn_mask = node.ipn_mask; + if (last == NULL) + ntop = ipn; + else + last->ipn_next = ipn; + last = ipn; + } + fclose(fp); + return ntop; +} + + +static void +setadflen(afp) + addrfamily_t *afp; +{ + afp->adf_len = offsetof(addrfamily_t, adf_addr); + switch (afp->adf_family) + { + case AF_INET : + afp->adf_len += sizeof(struct in_addr); + break; +#ifdef USE_INET6 + case AF_INET6 : + afp->adf_len += sizeof(struct in6_addr); + break; +#endif + default : + break; + } +} diff --git a/contrib/ipfilter/tools/ipscan_y.y b/contrib/ipfilter/tools/ipscan_y.y index 5dbefd6ab5ae..d323f054bd27 100644 --- a/contrib/ipfilter/tools/ipscan_y.y +++ b/contrib/ipfilter/tools/ipscan_y.y @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -13,6 +13,7 @@ #include "kmem.h" #include "ipscan_l.h" #include "netinet/ip_scan.h" +#include <ctype.h> #define YYDEBUG 1 @@ -60,7 +61,7 @@ int fd = -1; %token <num> YY_NUMBER YY_HEX %token <str> YY_STR -%token YY_COMMENT +%token YY_COMMENT %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT %token YY_RANGE_OUT YY_RANGE_IN %token <ip6> YY_IPV6 diff --git a/contrib/ipfilter/tools/ipsyncm.c b/contrib/ipfilter/tools/ipsyncm.c index 600d39ad0d6c..41513fae3bcc 100644 --- a/contrib/ipfilter/tools/ipsyncm.c +++ b/contrib/ipfilter/tools/ipsyncm.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsyncm.c,v 1.4.2.5 2006/08/26 11:21:14 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/time.h> @@ -49,13 +49,13 @@ static void handleterm(int sig) } #endif - + /* should be large enough to hold header + any datatype */ #define BUFFERLEN 1400 int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { struct sockaddr_in sin; char buff[BUFFERLEN]; @@ -66,14 +66,14 @@ char *argv[]; u_32_t magic; synchdr_t *sh; char *progname; - + progname = strrchr(argv[0], '/'); if (progname) { progname++; } else { progname = argv[0]; } - + if (argc < 2) { usage(progname); @@ -108,13 +108,13 @@ char *argv[]; syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); goto tryagain; } - + nfd = socket(AF_INET, SOCK_DGRAM, 0); if (nfd == -1) { syslog(LOG_ERR, "Socket :%m"); goto tryagain; } - + if (connect(nfd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { syslog(LOG_ERR, "Connect: %m"); goto tryagain; @@ -122,15 +122,15 @@ char *argv[]; syslog(LOG_INFO, "Sending data to %s", inet_ntoa(sin.sin_addr)); - - inbuf = 0; + + inbuf = 0; while (1) { n1 = read(lfd, buff+inbuf, BUFFERLEN-inbuf); - + printf("header : %d bytes read (header = %d bytes)\n", - n1, sizeof(*sh)); - + n1, (int) sizeof(*sh)); + if (n1 < 0) { syslog(LOG_ERR, "Read error (header): %m"); goto tryagain; @@ -143,8 +143,8 @@ char *argv[]; sleep(1); continue; } - - inbuf += n1; + + inbuf += n1; moreinbuf: if (inbuf < sizeof(*sh)) { @@ -153,7 +153,7 @@ moreinbuf: sh = (synchdr_t *)buff; len = ntohl(sh->sm_len); - magic = ntohl(sh->sm_magic); + magic = ntohl(sh->sm_magic); if (magic != SYNHDRMAGIC) { syslog(LOG_ERR, @@ -181,8 +181,8 @@ moreinbuf: printf(" table:Unknown(%d)", sh->sm_table); printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); -#endif - +#endif + if (inbuf < sizeof(*sh) + len) { continue; /* need more data */ goto tryagain; @@ -195,9 +195,9 @@ moreinbuf: } else if (sh->sm_cmd == SMC_UPDATE) { su = (syncupdent_t *)buff; if (sh->sm_p == IPPROTO_TCP) { - printf(" TCP Update: age %lu state %d/%d\n", + printf(" TCP Update: age %lu state %d/%d\n", su->sup_tcp.stu_age, - su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[0], su->sup_tcp.stu_state[1]); } } else { @@ -212,7 +212,7 @@ moreinbuf: goto tryagain; } - + if (n3 != n2) { syslog(LOG_ERR, "Incomplete write (%d/%d)", n3, n2); @@ -226,7 +226,7 @@ moreinbuf: /* move buffer to the front,we might need to make * this more efficient, by using a rolling pointer * over the buffer and only copying it, when - * we are reaching the end + * we are reaching the end */ inbuf -= n2; if (inbuf) { diff --git a/contrib/ipfilter/tools/ipsyncs.c b/contrib/ipfilter/tools/ipsyncs.c index 887eeab310c6..43692cd6a0d1 100644 --- a/contrib/ipfilter/tools/ipsyncs.c +++ b/contrib/ipfilter/tools/ipsyncs.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2001-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipsyncs.c,v 1.5.2.4 2006/08/26 11:21:15 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id$"; #endif #include <sys/types.h> #include <sys/time.h> @@ -54,10 +54,10 @@ static void handleterm(int sig) #define BUFFERLEN 1400 int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { - int nfd = -1 , lfd = -1; + int nfd = -1 , lfd = -1; int n1, n2, n3, magic, len, inbuf; struct sockaddr_in sin; struct sockaddr_in in; @@ -66,14 +66,14 @@ char *argv[]; syncupdent_t *su; synchdr_t *sh; char *progname; - + progname = strrchr(argv[0], '/'); if (progname) { progname++; } else { progname = argv[0]; } - + if (argc < 2) { usage(progname); exit(1); @@ -86,7 +86,7 @@ char *argv[]; #endif openlog(progname, LOG_PID, LOG_SECURITY); - + lfd = open(IPSYNC_NAME, O_WRONLY); if (lfd == -1) { syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); @@ -101,14 +101,14 @@ char *argv[]; sin.sin_port = htons(atoi(argv[2])); else sin.sin_port = htons(43434); - if (argc > 3) + if (argc > 3) in.sin_addr.s_addr = inet_addr(argv[3]); else in.sin_addr.s_addr = 0; in.sin_port = 0; while(1) { - + if (lfd != -1) close(lfd); if (nfd != -1) @@ -119,7 +119,7 @@ char *argv[]; syslog(LOG_ERR, "Opening %s :%m", IPSYNC_NAME); goto tryagain; } - + nfd = socket(AF_INET, SOCK_DGRAM, 0); if (nfd == -1) { syslog(LOG_ERR, "Socket :%m"); @@ -135,20 +135,20 @@ char *argv[]; } syslog(LOG_INFO, "Listening to %s", inet_ntoa(sin.sin_addr)); - - inbuf = 0; + + inbuf = 0; while (1) { - /* + /* * XXX currently we do not check the source address * of a datagram, this can be a security risk */ n1 = read(nfd, buff+inbuf, BUFFERLEN-inbuf); - + printf("header : %d bytes read (header = %d bytes)\n", - n1, sizeof(*sh)); - + n1, (int) sizeof(*sh)); + if (n1 < 0) { syslog(LOG_ERR, "Read error (header): %m"); goto tryagain; @@ -161,8 +161,8 @@ char *argv[]; sleep(1); continue; } - - inbuf += n1; + + inbuf += n1; moreinbuf: if (inbuf < sizeof(*sh)) { @@ -171,7 +171,7 @@ moreinbuf: sh = (synchdr_t *)buff; len = ntohl(sh->sm_len); - magic = ntohl(sh->sm_magic); + magic = ntohl(sh->sm_magic); if (magic != SYNHDRMAGIC) { syslog(LOG_ERR, "Invalid header magic %x", @@ -199,8 +199,8 @@ moreinbuf: printf(" table:Unknown(%d)", sh->sm_table); printf(" num:%d\n", (u_32_t)ntohl(sh->sm_num)); -#endif - +#endif + if (inbuf < sizeof(*sh) + len) { continue; /* need more data */ goto tryagain; @@ -213,9 +213,9 @@ moreinbuf: } else if (sh->sm_cmd == SMC_UPDATE) { su = (syncupdent_t *)buff; if (sh->sm_p == IPPROTO_TCP) { - printf(" TCP Update: age %lu state %d/%d\n", + printf(" TCP Update: age %lu state %d/%d\n", su->sup_tcp.stu_age, - su->sup_tcp.stu_state[0], + su->sup_tcp.stu_state[0], su->sup_tcp.stu_state[1]); } } else { @@ -231,7 +231,7 @@ moreinbuf: goto tryagain; } - + if (n3 != n2) { syslog(LOG_ERR, "%s: Incomplete write (%d/%d)", IPSYNC_NAME, n3, n2); @@ -245,7 +245,7 @@ moreinbuf: /* move buffer to the front,we might need to make * this more efficient, by using a rolling pointer * over the buffer and only copying it, when - * we are reaching the end + * we are reaching the end */ inbuf -= n2; if (inbuf) { diff --git a/contrib/ipfilter/tools/lex_var.h b/contrib/ipfilter/tools/lex_var.h index 78c5efc4263d..eb59f5887cba 100644 --- a/contrib/ipfilter/tools/lex_var.h +++ b/contrib/ipfilter/tools/lex_var.h @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ diff --git a/contrib/ipfilter/tools/lexer.c b/contrib/ipfilter/tools/lexer.c index 989643c966b5..41b7896090ad 100644 --- a/contrib/ipfilter/tools/lexer.c +++ b/contrib/ipfilter/tools/lexer.c @@ -1,7 +1,7 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002-2006 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ @@ -42,6 +42,7 @@ char yychars[YYBUFSIZ+1]; int yylineNum = 1; int yypos = 0; int yylast = -1; +int yydictfixed = 0; int yyexpectaddr = 0; int yybreakondot = 0; int yyvarnext = 0; @@ -60,7 +61,7 @@ static void yystrtotext __P((char *)); static char *yytexttochar __P((void)); static int yygetc(docont) -int docont; + int docont; { int c; @@ -98,7 +99,7 @@ int docont; static void yyunputc(c) -int c; + int c; { if (c == '\n') yylineNum--; @@ -107,7 +108,7 @@ int c; static int yyswallow(last) -int last; + int last; { int c; @@ -134,7 +135,7 @@ static char *yytexttochar() static void yystrtotext(str) -char *str; + char *str; { int len; char *s; @@ -150,7 +151,7 @@ char *str; static char *yytexttostr(offset, max) -int offset, max; + int offset, max; { char *str; int i; @@ -175,8 +176,11 @@ int offset, max; int yylex() { + static int prior = 0; + static int priornum = 0; int c, n, isbuilding, rval, lnext, nokey = 0; char *name; + int triedv6 = 0; isbuilding = 0; lnext = 0; @@ -190,7 +194,8 @@ int yylex() nextchar: c = yygetc(0); if (yydebug > 1) - printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos, yytexttochar()); + printf("yygetc = (%x) %c [%*.*s]\n", + c, c, yypos, yypos, yytexttochar()); switch (c) { @@ -209,6 +214,8 @@ nextchar: sizeof(yytext[0]) * (yylast - yypos + 1)); } yylast -= yypos; + if (yyexpectaddr == 2) + yyexpectaddr = 0; yypos = 0; lnext = 0; nokey = 0; @@ -232,6 +239,7 @@ nextchar: if (lnext == 1) { lnext = 0; if ((isbuilding == 0) && !ISALNUM(c)) { + prior = c; return c; } goto nextchar; @@ -246,7 +254,7 @@ nextchar: } yyswallow('\n'); rval = YY_COMMENT; - goto nextchar; + goto done; case '$' : if (isbuilding == 1) { @@ -320,6 +328,9 @@ nextchar: yybreakondot = 0; yyvarnext = 0; yytokentype = 0; + if (yydebug) + fprintf(stderr, "reset at EOF\n"); + prior = 0; return 0; } @@ -344,16 +355,21 @@ nextchar: switch (c) { case '-' : - if (yyexpectaddr) - break; - if (isbuilding == 1) - break; n = yygetc(0); if (n == '>') { isbuilding = 1; goto done; } yyunputc(n); + if (yyexpectaddr) { + if (isbuilding == 1) + yyunputc(c); + else + rval = '-'; + goto done; + } + if (isbuilding == 1) + break; rval = '-'; goto done; @@ -420,14 +436,21 @@ nextchar: * 0000:0000:0000:0000:0000:0000:0000:0000 */ #ifdef USE_INET6 - if (yyexpectaddr == 1 && isbuilding == 0 && (ishex(c) || c == ':')) { + if (yyexpectaddr != 0 && isbuilding == 0 && + (ishex(c) || isdigit(c) || c == ':')) { char ipv6buf[45 + 1], *s, oc; int start; +buildipv6: start = yypos; s = ipv6buf; oc = c; + if (prior == YY_NUMBER && c == ':') { + sprintf(s, "%d", priornum); + s += strlen(s); + } + /* * Perhaps we should implement stricter controls on what we * swallow up here, but surely it would just be duplicating @@ -451,7 +474,25 @@ nextchar: } #endif - if (c == ':') { + if ((c == ':') && (rval != YY_IPV6) && (triedv6 == 0)) { +#ifdef USE_INET6 + yystr = yytexttostr(0, yypos - 1); + if (yystr != NULL) { + char *s; + + for (s = yystr; *s && ishex(*s); s++) + ; + if (!*s && *yystr) { + isbuilding = 0; + c = *yystr; + free(yystr); + triedv6 = 1; + yypos = 1; + goto buildipv6; + } + free(yystr); + } +#endif if (isbuilding == 1) { yyunputc(c); goto done; @@ -492,8 +533,8 @@ done: yystr = yytexttostr(0, yypos); if (yydebug) - printf("isbuilding %d yyvarnext %d nokey %d\n", - isbuilding, yyvarnext, nokey); + printf("isbuilding %d yyvarnext %d nokey %d fixed %d addr %d\n", + isbuilding, yyvarnext, nokey, yydictfixed, yyexpectaddr); if (isbuilding == 1) { wordtab_t *w; @@ -502,7 +543,7 @@ done: if ((yyvarnext == 0) && (nokey == 0)) { w = yyfindkey(yystr); - if (w == NULL && yywordtab != NULL) { + if (w == NULL && yywordtab != NULL && !yydictfixed) { yyresetdict(); w = yyfindkey(yystr); } @@ -514,14 +555,19 @@ done: rval = YY_STR; } - if (rval == YY_STR && yysavedepth > 0) - yyresetdict(); + if (rval == YY_STR) { + if (yysavedepth > 0 && !yydictfixed) + yyresetdict(); + if (yyexpectaddr != 0) + yyexpectaddr = 0; + } yytokentype = rval; if (yydebug) - printf("lexed(%s) [%d,%d,%d] => %d @%d\n", yystr, string_start, - string_end, pos, rval, yysavedepth); + printf("lexed(%s) %d,%d,%d [%d,%d,%d] => %d @%d\n", + yystr, isbuilding, yyexpectaddr, yysavedepth, + string_start, string_end, pos, rval, yysavedepth); switch (rval) { @@ -548,12 +594,15 @@ done: yypos = 0; } + if (rval == YY_NUMBER) + priornum = yylval.num; + prior = rval; return rval; } static wordtab_t *yyfindkey(key) -char *key; + char *key; { wordtab_t *w; @@ -568,7 +617,7 @@ char *key; char *yykeytostr(num) -int num; + int num; { wordtab_t *w; @@ -583,7 +632,7 @@ int num; wordtab_t *yysettab(words) -wordtab_t *words; + wordtab_t *words; { wordtab_t *save; @@ -594,7 +643,7 @@ wordtab_t *words; void yyerror(msg) -char *msg; + char *msg; { char *txt, letter[2]; int freetxt = 0; @@ -620,9 +669,31 @@ char *msg; } +void yysetfixeddict(newdict) + wordtab_t *newdict; +{ + if (yydebug) + printf("yysetfixeddict(%lx)\n", (u_long)newdict); + + if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) { + fprintf(stderr, "%d: at maximum dictionary depth\n", + yylineNum); + return; + } + + yysavewords[yysavedepth++] = yysettab(newdict); + if (yydebug) + printf("yysavedepth++ => %d\n", yysavedepth); + yydictfixed = 1; +} + + void yysetdict(newdict) -wordtab_t *newdict; + wordtab_t *newdict; { + if (yydebug) + printf("yysetdict(%lx)\n", (u_long)newdict); + if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) { fprintf(stderr, "%d: at maximum dictionary depth\n", yylineNum); @@ -643,14 +714,15 @@ void yyresetdict() if (yydebug) printf("yysavedepth-- => %d\n", yysavedepth); } + yydictfixed = 0; } #ifdef TEST_LEXER int main(argc, argv) -int argc; -char *argv[]; + int argc; + char *argv[]; { int n; diff --git a/contrib/ipfilter/tools/lexer.h b/contrib/ipfilter/tools/lexer.h index d973ea42ae35..cff24b4eb402 100644 --- a/contrib/ipfilter/tools/lexer.h +++ b/contrib/ipfilter/tools/lexer.h @@ -1,16 +1,11 @@ /* $FreeBSD$ */ /* - * Copyright (C) 2002-2004 by Darren Reed. + * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ -typedef struct wordtab { - char *w_word; - int w_value; -} wordtab_t; - #ifdef NO_YACC #define YY_COMMENT 1000 #define YY_CMP_NE 1001 @@ -29,6 +24,7 @@ typedef struct wordtab { extern wordtab_t *yysettab __P((wordtab_t *)); extern void yysetdict __P((wordtab_t *)); +extern void yysetfixeddict __P((wordtab_t *)); extern int yylex __P((void)); extern void yyerror __P((char *)); extern char *yykeytostr __P((int)); |
