diff --git a/sbin/ipf/common/genmask.c b/sbin/ipf/common/genmask.c index 75193e3ea398..581573463c4c 100644 --- a/sbin/ipf/common/genmask.c +++ b/sbin/ipf/common/genmask.c @@ -1,68 +1,68 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int genmask(family, msk, mskp) int family; char *msk; i6addr_t *mskp; { char *endptr = 0L; u_32_t addr; int bits; if (strchr(msk, '.') || strchr(msk, 'x') || strchr(msk, ':')) { /* possibly of the form xxx.xxx.xxx.xxx * or 0xYYYYYYYY */ switch (family) { #ifdef USE_INET6 case AF_INET6 : if (inet_pton(AF_INET6, msk, &mskp->in4) != 1) - return -1; + return(-1); break; #endif case AF_INET : if (inet_aton(msk, &mskp->in4) == 0) - return -1; + return(-1); break; default : - return -1; + return(-1); /*NOTREACHED*/ } } else { /* * set x most significant bits */ bits = (int)strtol(msk, &endptr, 0); switch (family) { case AF_INET6 : if ((*endptr != '\0') || (bits < 0) || (bits > 128)) - return -1; + return(-1); fill6bits(bits, mskp->i6); break; case AF_INET : if (*endptr != '\0' || bits > 32 || bits < 0) - return -1; + return(-1); if (bits == 0) addr = 0; else addr = htonl(0xffffffff << (32 - bits)); mskp->in4.s_addr = addr; break; default : - return -1; + return(-1); /*NOTREACHED*/ } } - return 0; + return(0); } diff --git a/sbin/ipf/common/ipf_y.y b/sbin/ipf/common/ipf_y.y index 861d0ccd9a13..ad4200023781 100644 --- a/sbin/ipf/common/ipf_y.y +++ b/sbin/ipf/common/ipf_y.y @@ -1,2738 +1,2738 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include "ipf.h" #include #include #include #ifdef IPFILTER_BPF # include #endif #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #include "netinet/ipl.h" #include "ipf_l.h" #define YYDEBUG 1 #define DOALL(x) for (fr = frc; fr != NULL; fr = fr->fr_next) { x } #define DOREM(x) for (; fr != NULL; fr = fr->fr_next) { x } extern void yyerror(char *); extern int yyparse(void); extern int yylex(void); extern int yydebug; extern FILE *yyin; extern int yylineNum; static int addname(frentry_t **, char *); static frentry_t *addrule(void); static frentry_t *allocfr(void); static void build_dstaddr_af(frentry_t *, void *); static void build_srcaddr_af(frentry_t *, void *); static void dobpf(int, char *); static void doipfexpr(char *); static void do_tuneint(char *, int); static void do_tunestr(char *, char *); static void fillgroup(frentry_t *); static int lookuphost(char *, i6addr_t *); static u_int makehash(struct alist_s *); static int makepool(struct alist_s *); static struct alist_s *newalist(struct alist_s *); static void newrule(void); static void resetaddr(void); static void setgroup(frentry_t **, char *); static void setgrhead(frentry_t **, char *); static void seticmphead(frentry_t **, char *); static void setifname(frentry_t **, int, char *); static void setipftype(void); static void setsyslog(void); static void unsetsyslog(void); frentry_t *fr = NULL, *frc = NULL, *frtop = NULL, *frold = NULL; static int ifpflag = 0; static int nowith = 0; static int dynamic = -1; static int pooled = 0; static int hashed = 0; static int nrules = 0; static int newlist = 0; static int added = 0; static int ipffd = -1; static int *yycont = NULL; static ioctlfunc_t ipfioctls[IPL_LOGSIZE]; static addfunc_t ipfaddfunc = NULL; %} %union { char *str; u_32_t num; 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 ipp_s { int type; int ifpos; int f; int v; int lif; union i6addr a; union i6addr m; char *name; } ipp; struct { i6addr_t adr; int f; } adr; i6addr_t ip6; struct { char *if1; char *if2; } ifs; char gname[FR_GROUPLEN]; }; %type portnum %type facility priority icmpcode seclevel secname icmptype %type opt compare range opttype flagset optlist ipv6hdrlist ipv6hdr %type portc porteq ipmask maskopts %type ipv4 ipv4_16 ipv4_24 %type hostname %type addr ipaddr %type servicename name interfacename groupname %type portrange portcomp %type addrlist poollist %type onname %token YY_NUMBER YY_HEX %token 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 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 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 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_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_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 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 %token IPFY_IPOPT_SATID IPFY_IPOPT_SSRR IPFY_IPOPT_ADDEXT IPFY_IPOPT_VISA %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 IPFY_DOI %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 %token IPFY_ICMPT_REDIR IPFY_ICMPT_TIMEX IPFY_ICMPT_PARAMP IPFY_ICMPT_TIMEST %token IPFY_ICMPT_TIMESTREP IPFY_ICMPT_INFOREQ IPFY_ICMPT_INFOREP %token IPFY_ICMPT_MASKREQ IPFY_ICMPT_MASKREP IPFY_ICMPT_ROUTERAD %token IPFY_ICMPT_ROUTERSOL %token IPFY_ICMPC_NETUNR IPFY_ICMPC_HSTUNR IPFY_ICMPC_PROUNR IPFY_ICMPC_PORUNR %token IPFY_ICMPC_NEEDF IPFY_ICMPC_SRCFAIL IPFY_ICMPC_NETUNK IPFY_ICMPC_HSTUNK %token IPFY_ICMPC_ISOLATE IPFY_ICMPC_NETPRO IPFY_ICMPC_HSTPRO %token IPFY_ICMPC_NETTOS IPFY_ICMPC_HSTTOS IPFY_ICMPC_FLTPRO IPFY_ICMPC_HSTPRE %token IPFY_ICMPC_CUTPRE %token IPFY_FAC_KERN IPFY_FAC_USER IPFY_FAC_MAIL IPFY_FAC_DAEMON IPFY_FAC_AUTH %token IPFY_FAC_SYSLOG IPFY_FAC_LPR IPFY_FAC_NEWS IPFY_FAC_UUCP IPFY_FAC_CRON %token IPFY_FAC_LOCAL0 IPFY_FAC_LOCAL1 IPFY_FAC_LOCAL2 IPFY_FAC_LOCAL3 %token IPFY_FAC_LOCAL4 IPFY_FAC_LOCAL5 IPFY_FAC_LOCAL6 IPFY_FAC_LOCAL7 %token IPFY_FAC_SECURITY IPFY_FAC_FTP IPFY_FAC_AUTHPRIV IPFY_FAC_AUDIT %token IPFY_FAC_LFMT IPFY_FAC_CONSOLE %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: settings rules | rules ; settings: YY_COMMENT | setting | settings setting ; rules: line | 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; 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; } resetlexer(); } | YY_COMMENT ; xx: { newrule(); } ; assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; } ; assigning: '=' { yyvarnext = 1; } ; rule: inrule eol | outrule eol ; eol: | ';' ; inrule: rulehead markin inopts rulemain ruletail intag ruletail2 ; outrule: rulehead markout outopts rulemain ruletail outtag ruletail2 ; rulehead: xx collection action | xx insert collection action ; markin: IPFY_IN { fr->fr_flags |= FR_INQUE; } ; markout: IPFY_OUT { fr->fr_flags |= FR_OUTQUE; } ; rulemain: ipfrule | bpfrule | exprrule ; ipfrule: 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: IPFY_BPFV4 '{' YY_STR '}' { dobpf(4, $3); free($3); } | 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 rulettl comment ; intag: settagin matchtagin ; outtag: settagout matchtagout ; insert: '@' YY_NUMBER { fr->fr_hits = (U_QUAD_T)$2 + 1; } ; collection: | YY_NUMBER { fr->fr_collect = $1; } ; action: block | IPFY_PASS { fr->fr_flags |= FR_PASS; } | 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; } | IPFY_CALL func | IPFY_CALL IPFY_NOW func { fr->fr_flags |= FR_CALLNOW; } ; block: blocked | blocked blockreturn ; blocked: IPFY_BLOCK { fr->fr_flags = FR_BLOCK; } ; blockreturn: IPFY_RETICMP { fr->fr_flags |= FR_RETICMP; } | IPFY_RETICMP returncode { fr->fr_flags |= FR_RETICMP; } | IPFY_RETICMPASDST { fr->fr_flags |= FR_FAKEICMP; } | IPFY_RETICMPASDST returncode { fr->fr_flags |= FR_FAKEICMP; } | 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; } ; auth: IPFY_AUTH { fr->fr_flags |= FR_AUTH; } | IPFY_AUTH blockreturn { fr->fr_flags |= FR_AUTH;} | IPFY_PREAUTH { fr->fr_flags |= FR_PREAUTH; } ; func: YY_STR '/' YY_NUMBER { fr->fr_func = nametokva($1, ipfioctls[IPL_LOGIPF]); fr->fr_arg = $3; free($1); } ; inopts: | inopts inopt ; inopt: logopt | quick | on | dup | froute | proute | replyto ; outopts: | outopts outopt ; outopt: logopt | quick | on | dup | proute | froute | replyto ; tos: | settos YY_NUMBER { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } | settos YY_HEX { DOALL(fr->fr_tos = $2; fr->fr_mtos = 0xff;) } | settos lstart toslist lend ; settos: IPFY_TOS { setipftype(); } ; toslist: YY_NUMBER { DOALL(fr->fr_tos = $1; fr->fr_mtos = 0xff;) } | 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 { DOREM(fr->fr_tos = $3; fr->fr_mtos = 0xff;) } ; ttl: | setttl YY_NUMBER { DOALL(fr->fr_ttl = $2; fr->fr_mttl = 0xff;) } | setttl lstart ttllist lend ; lstart: '{' { newlist = 1; fr = frc; added = 0; } ; lend: '}' { nrules += added; } ; lmore: lanother { if (newlist == 1) { newlist = 0; } fr = addrule(); if (yycont != NULL) *yycont = 1; } ; lanother: | ',' ; setttl: IPFY_TTL { setipftype(); } ; ttllist: YY_NUMBER { DOREM(fr->fr_ttl = $1; fr->fr_mttl = 0xff;) } | ttllist lmore YY_NUMBER { DOREM(fr->fr_ttl = $3; fr->fr_mttl = 0xff;) } ; proto: | protox protocol { yyresetdict(); } ; protox: IPFY_PROTO { setipftype(); fr = frc; yysetdict(NULL); } ; ip: srcdst flags icmp ; group: | IPFY_GROUP groupname { DOALL(setgroup(&fr, $2); \ fillgroup(fr);); free($2); } ; head: | IPFY_HEAD groupname { DOALL(setgrhead(&fr, $2);); free($2); } ; groupname: YY_STR { $$ = $1; if (strlen($$) >= FR_GROUPLEN) $$[FR_GROUPLEN - 1] = '\0'; } | YY_NUMBER { $$ = malloc(16); sprintf($$, "%d", $1); } ; settagin: | IPFY_SETTAG '(' taginlist ')' ; taginlist: taginspec | taginlist ',' taginspec ; taginspec: logtag ; nattag: IPFY_NAT '=' YY_STR { DOALL(strncpy(fr->fr_nattag.ipt_tag,\ $3, IPFTAG_LEN);); free($3); } | IPFY_NAT '=' YY_NUMBER { DOALL(sprintf(fr->fr_nattag.ipt_tag,\ "%d", $3 & 0xffffffff);) } ; logtag: IPFY_LOG '=' YY_NUMBER { DOALL(fr->fr_logtag = $3;) } ; settagout: | IPFY_SETTAG '(' tagoutlist ')' ; tagoutlist: tagoutspec | tagoutlist ',' tagoutspec ; tagoutspec: logtag | nattag ; matchtagin: | IPFY_MATCHTAG '(' tagoutlist ')' ; matchtagout: | IPFY_MATCHTAG '(' taginlist ')' ; 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: '{' ; restoregroup: '}' ; logopt: log ; quick: IPFY_QUICK { fr->fr_flags |= FR_QUICK; } ; 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 { 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(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 { $$.if1 = $1; $$.if2 = NULL; } | interfacename ',' interfacename { $$.if1 = $1; $$.if2 = $3; } ; vianame: 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 { int idx = addname(&fr, $2); fr->fr_dif.fd_name = idx; 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 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); } ; duptoseparator: ':' { yyexpectaddr = 1; yycont = &yyexpectaddr; resetaddr(); } ; froute: IPFY_FROUTE { fr->fr_flags |= FR_FASTROUTE; } ; proute: routeto name { int idx = addname(&fr, $2); fr->fr_tif.fd_name = idx; 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 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); } ; routeto: IPFY_TO | IPFY_ROUTETO ; replyto: IPFY_REPLY_TO name { 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 { 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); } ; logoptions: logoption | logoptions logoption ; logoption: IPFY_BODY { fr->fr_flags |= FR_LOGBODY; } | IPFY_FIRST { fr->fr_flags |= FR_LOGFIRST; } | IPFY_ORBLOCK { fr->fr_flags |= FR_LOGORBLOCK; } | level loglevel { unsetsyslog(); } ; returncode: starticmpcode icmpcode ')' { fr->fr_icode = $2; yyresetdict(); } ; starticmpcode: '(' { yysetdict(icmpcodewords); } ; srcdst: | IPFY_ALL | fromto ; protocol: YY_NUMBER { DOALL(fr->fr_proto = $1; \ fr->fr_mproto = 0xff;) } | YY_STR { if (!strcmp($1, "tcp-udp")) { DOALL(fr->fr_flx |= FI_TCPUDP; \ fr->fr_mflx |= FI_TCPUDP;) } else { int p = getproto($1); if (p == -1) yyerror("protocol unknown"); 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 { YYERROR; } free($1); free($3); } ; nextstring: '/' { yysetdict(NULL); } ; fromto: from srcobject to dstobject { yyexpectaddr = 0; yycont = NULL; } | to dstobject { yyexpectaddr = 0; yycont = NULL; } | from srcobject { yyexpectaddr = 0; yycont = NULL; } ; from: IPFY_FROM { setipftype(); if (fr == NULL) fr = frc; yyexpectaddr = 1; if (yydebug) printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); resetaddr(); } ; to: IPFY_TO { if (fr == NULL) fr = frc; yyexpectaddr = 1; if (yydebug) printf("set yyexpectaddr\n"); yycont = &yyexpectaddr; yysetdict(addrwords); resetaddr(); } ; with: | andwith withlist ; andwith: IPFY_WITH { nowith = 0; setipftype(); } | IPFY_AND { nowith = 0; setipftype(); } ; 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;) } | startflags '/' flagset { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } | startflags YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = FR_TCPFMAX;) } | startflags '/' YY_NUMBER { DOALL(fr->fr_tcpf = 0; fr->fr_tcpfm = $3;) } | startflags YY_NUMBER '/' YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } | startflags flagset '/' YY_NUMBER { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } | startflags YY_NUMBER '/' flagset { DOALL(fr->fr_tcpf = $2; fr->fr_tcpfm = $4;) } ; startflags: IPFY_FLAGS { if (frc->fr_type != FR_T_IPF) yyerror("flags with non-ipf type rule"); if (frc->fr_proto != IPPROTO_TCP) yyerror("flags with non-TCP rule"); } ; flagset: YY_STR { $$ = tcpflags($1); free($1); } | YY_HEX { $$ = $1; } ; srcobject: { yyresetdict(); } fromport | srcaddr srcport | '!' srcaddr srcport { DOALL(fr->fr_flags |= FR_NOTSRCIP;) } ; srcaddr: addr { build_srcaddr_af(fr, &$1); } | lstart srcaddrlist lend ; srcaddrlist: addr { build_srcaddr_af(fr, &$1); } | srcaddrlist lmore addr { build_srcaddr_af(fr, &$3); } ; srcport: | portcomp { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } | portrange { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ fr->fr_stop = $1.p2;) } | porteq lstart srcportlist lend { yyresetdict(); } ; fromport: portcomp { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1;) } | portrange { DOALL(fr->fr_scmp = $1.pc; fr->fr_sport = $1.p1; \ fr->fr_stop = $1.p2;) } | porteq lstart srcportlist lend { yyresetdict(); } ; srcportlist: portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $1;) } | portnum ':' portnum { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } | portnum YY_RANGE_IN portnum { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $1; \ fr->fr_stop = $3;) } | srcportlist lmore portnum { DOREM(fr->fr_scmp = FR_EQUAL; fr->fr_sport = $3;) } | srcportlist lmore portnum ':' portnum { DOREM(fr->fr_scmp = FR_INCRANGE; fr->fr_sport = $3; \ fr->fr_stop = $5;) } | srcportlist lmore portnum YY_RANGE_IN portnum { DOREM(fr->fr_scmp = FR_INRANGE; fr->fr_sport = $3; \ fr->fr_stop = $5;) } ; dstobject: { yyresetdict(); } toport | dstaddr dstport | '!' dstaddr dstport { DOALL(fr->fr_flags |= FR_NOTDSTIP;) } ; dstaddr: 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 { 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 { 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); } ; dstport: | portcomp { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } | portrange { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ fr->fr_dtop = $1.p2;) } | porteq lstart dstportlist lend { yyresetdict(); } ; toport: portcomp { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1;) } | portrange { DOALL(fr->fr_dcmp = $1.pc; fr->fr_dport = $1.p1; \ fr->fr_dtop = $1.p2;) } | porteq lstart dstportlist lend { yyresetdict(); } ; dstportlist: portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $1;) } | portnum ':' portnum { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } | portnum YY_RANGE_IN portnum { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $1; \ fr->fr_dtop = $3;) } | dstportlist lmore portnum { DOREM(fr->fr_dcmp = FR_EQUAL; fr->fr_dport = $3;) } | dstportlist lmore portnum ':' portnum { DOREM(fr->fr_dcmp = FR_INCRANGE; fr->fr_dport = $3; \ fr->fr_dtop = $5;) } | dstportlist lmore portnum YY_RANGE_IN portnum { DOREM(fr->fr_dcmp = FR_INRANGE; fr->fr_dport = $3; \ fr->fr_dtop = $5;) } ; 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; $$.a.iplookupname = addname(&fr, $3); } | pool '=' '(' { yyexpectaddr = 1; 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($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 { hashed = 1; $$.type = FRI_LOOKUP; $$.v = 0; $$.ifpos = -1; $$.f = AF_UNSPEC; $$.a.iplookuptype = IPLT_HASH; $$.a.iplookupsubtype = 1; $$.a.iplookupname = addname(&fr, $3); } | 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($5); } | ipaddr { $$ = $1; yyexpectaddr = 0; } ; ipaddr: IPFY_ANY { memset(&($$), 0, sizeof($$)); $$.type = FRI_NORMAL; $$.ifpos = -1; yyexpectaddr = 0; } | hostname { memset(&($$), 0, sizeof($$)); $$.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 { memset(&($$), 0, sizeof($$)); 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; } | '(' YY_STR ')' { memset(&($$), 0, sizeof($$)); $$.type = FRI_DYNAMIC; ifpflag = FRI_DYNAMIC; $$.ifpos = addname(&fr, $2); $$.lif = 0; } | '(' YY_STR ')' '/' { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } maskopts { memset(&($$), 0, sizeof($$)); $$.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_STR ':' YY_NUMBER ')' '/' { ifpflag = FRI_DYNAMIC; yysetdict(maskwords); } maskopts { memset(&($$), 0, sizeof($$)); $$.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; } ; maskspace: '/' | IPFY_MASK ; 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 { YYERROR; } $$ = 0; } | IPFY_NETWORK { if (ifpflag == FRI_DYNAMIC) { ifpflag = FRI_NETWORK; } else { YYERROR; } $$ = 0; } | IPFY_NETMASKED { if (ifpflag == FRI_DYNAMIC) { ifpflag = FRI_NETMASKED; } else { YYERROR; } $$ = 0; } | IPFY_PEER { if (ifpflag == FRI_DYNAMIC) { ifpflag = FRI_PEERADDR; } else { YYERROR; } $$ = 0; } | YY_NUMBER { $$ = $1; } ; hostname: ipv4 { memset(&($$), 0, sizeof($$)); $$.adr.in4 = $1; if (frc->fr_family == AF_INET6) YYERROR; $$.f = AF_INET; yyexpectaddr = 2; } | YY_NUMBER { memset(&($$), 0, sizeof($$)); if (frc->fr_family == AF_INET6) YYERROR; $$.adr.in4_addr = $1; $$.f = AF_INET; yyexpectaddr = 2; } | YY_HEX { memset(&($$), 0, sizeof($$)); if (frc->fr_family == AF_INET6) YYERROR; $$.adr.in4_addr = $1; $$.f = AF_INET; yyexpectaddr = 2; } | YY_STR { memset(&($$), 0, sizeof($$)); if (lookuphost($1, &$$.adr) == 0) $$.f = AF_INET; free($1); yyexpectaddr = 2; } | YY_IPV6 { memset(&($$), 0, sizeof($$)); if (frc->fr_family == AF_INET) YYERROR; $$.adr = $1; $$.f = AF_INET6; yyexpectaddr = 2; } ; addrlist: ipaddr { $$ = newalist(NULL); $$->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(); } ; hash: IPFY_HASH { yyexpectaddr = 0; yycont = NULL; yyresetdict(); } ; poollist: ipaddr { $$ = newalist(NULL); $$->al_family = $1.f; $$->al_i6addr = $1.a; $$->al_i6mask = $1.m; } | '!' ipaddr { $$ = newalist(NULL); $$->al_not = 1; $$->al_family = $2.f; $$->al_i6addr = $2.a; $$->al_i6mask = $2.m; } | poollist ',' ipaddr { $$ = newalist($1); $$->al_family = $3.f; $$->al_i6addr = $3.a; $$->al_i6mask = $3.m; } | poollist ',' '!' ipaddr { $$ = newalist($1); $$->al_not = 1; $$->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); } | porteq { $$ = $1; } ; porteq: port '=' { $$ = FR_EQUAL; yysetdict(NULL); } ; portr: IPFY_PORT { yyexpectaddr = 0; yycont = NULL; yysetdict(NULL); } ; portcomp: portc portnum { $$.pc = $1; $$.p1 = $2; yyresetdict(); } ; portrange: portr portnum range portnum { $$.p1 = $2; $$.pc = $3; $$.p2 = $4; yyresetdict(); } ; icmp: | itype icode ; itype: seticmptype icmptype { DOALL(fr->fr_icmp = htons($2 << 8); fr->fr_icmpm = htons(0xff00);); yyresetdict(); } | seticmptype lstart typelist lend { yyresetdict(); } ; seticmptype: 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 { DOALL(fr->fr_icmp |= htons($2); fr->fr_icmpm |= htons(0xff);); yyresetdict(); } | seticmpcode lstart codelist lend { yyresetdict(); } ; seticmpcode: IPFY_ICMPCODE { yysetdict(icmpcodewords); } ; typelist: icmptype { DOREM(fr->fr_icmp = htons($1 << 8); fr->fr_icmpm = htons(0xff00);) } | typelist lmore icmptype { DOREM(fr->fr_icmp = htons($3 << 8); fr->fr_icmpm = htons(0xff00);) } ; codelist: icmpcode { DOREM(fr->fr_icmp |= htons($1); fr->fr_icmpm |= htons(0xff);) } | codelist lmore icmpcode { DOREM(fr->fr_icmp &= htons(0xff00); fr->fr_icmp |= htons($3); \ fr->fr_icmpm |= htons(0xff);) } ; age: | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ fr->fr_age[1] = $2;) } | IPFY_AGE YY_NUMBER '/' YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ fr->fr_age[1] = $4;) } ; keep: | IPFY_KEEP keepstate keep | IPFY_KEEP keepfrag keep ; keepstate: IPFY_STATE stateoptlist { DOALL(fr->fr_flags |= FR_KEEPSTATE;)} ; keepfrag: IPFY_FRAGS fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } | IPFY_FRAG fragoptlist { DOALL(fr->fr_flags |= FR_KEEPFRAG;) } ; fragoptlist: | '(' fragopts ')' ; fragopts: fragopt lanother fragopts | fragopt ; fragopt: IPFY_STRICT { DOALL(fr->fr_flags |= FR_FRSTRICT;) } ; stateoptlist: | '(' stateopts ')' ; stateopts: stateopt lanother stateopts | stateopt ; stateopt: IPFY_LIMIT YY_NUMBER { DOALL(fr->fr_statemax = $2;) } | IPFY_STRICT { DOALL(if (fr->fr_proto != IPPROTO_TCP) { \ YYERROR; \ } 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 \ fr->fr_flags |= FR_NEWISN;) } | IPFY_NOICMPERR { DOALL(fr->fr_flags |= FR_NOICMPERR;) } | IPFY_SYNC { DOALL(fr->fr_flags |= FR_STATESYNC;) } | IPFY_AGE YY_NUMBER { DOALL(fr->fr_age[0] = $2; \ fr->fr_age[1] = $2;) } | 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, &($$), NULL) == -1) yyerror("service unknown"); $$ = ntohs($$); free($1); } | YY_NUMBER { if ($1 > 65535) /* Unsigned */ yyerror("invalid port number"); else $$ = $1; } ; withlist: withopt { nowith = 0; } | withlist withopt { nowith = 0; } | withlist ',' withopt { nowith = 0; } ; withopt: opttype { DOALL(fr->fr_flx |= $1; fr->fr_mflx |= $1;) } | notwith opttype { DOALL(fr->fr_mflx |= $2;) } | ipopt ipopts { yyresetdict(); } | notwith ipopt ipopts { yyresetdict(); } | startv6hdr ipv6hdrs { yyresetdict(); } ; ipopt: IPFY_OPT { yysetdict(ipv4optwords); } ; startv6hdr: IPFY_V6HDR { if (frc->fr_family != AF_INET6) yyerror("only available with IPv6"); yysetdict(ipv6optwords); } ; notwith: IPFY_NOT { nowith = 1; } | IPFY_NO { nowith = 1; } ; opttype: IPFY_IPOPTS { $$ = FI_OPTIONS; } | IPFY_SHORT { $$ = FI_SHORT; } | IPFY_NAT { $$ = FI_NATED; } | IPFY_BAD { $$ = FI_BAD; } | IPFY_BADNAT { $$ = FI_BADNAT; } | IPFY_BADSRC { $$ = FI_BADSRC; } | IPFY_LOWTTL { $$ = FI_LOWTTL; } | IPFY_FRAG { $$ = FI_FRAG; } | IPFY_FRAGBODY { $$ = FI_FRAGBODY; } | IPFY_FRAGS { $$ = FI_FRAG; } | IPFY_MBCAST { $$ = FI_MBCAST; } | IPFY_MULTICAST { $$ = FI_MULTICAST; } | 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;) } ; optlist: opt { $$ |= $1; } | optlist ',' opt { $$ |= $1 | $3; } ; ipv6hdrs: ipv6hdrlist { DOALL(fr->fr_mip.fi_optmsk |= $1; if (!nowith) fr->fr_ip.fi_optmsk |= $1;) } ; ipv6hdrlist: ipv6hdr { $$ |= $1; } | ipv6hdrlist ',' ipv6hdr { $$ |= $1 | $3; } ; secname: seclevel { $$ |= $1; } | secname ',' seclevel { $$ |= $1 | $3; } ; seclevel: IPFY_SEC_UNC { $$ = secbit(IPSO_CLASS_UNCL); } | IPFY_SEC_CONF { $$ = secbit(IPSO_CLASS_CONF); } | IPFY_SEC_RSV1 { $$ = secbit(IPSO_CLASS_RES1); } | IPFY_SEC_RSV2 { $$ = secbit(IPSO_CLASS_RES2); } | IPFY_SEC_RSV3 { $$ = secbit(IPSO_CLASS_RES3); } | IPFY_SEC_RSV4 { $$ = secbit(IPSO_CLASS_RES4); } | IPFY_SEC_SEC { $$ = secbit(IPSO_CLASS_SECR); } | IPFY_SEC_TS { $$ = secbit(IPSO_CLASS_TOPS); } ; icmptype: YY_NUMBER { $$ = $1; } | YY_STR { $$ = geticmptype(frc->fr_family, $1); if ($$ == -1) yyerror("unrecognised icmp type"); } ; icmpcode: YY_NUMBER { $$ = $1; } | IPFY_ICMPC_NETUNR { $$ = ICMP_UNREACH_NET; } | IPFY_ICMPC_HSTUNR { $$ = ICMP_UNREACH_HOST; } | IPFY_ICMPC_PROUNR { $$ = ICMP_UNREACH_PROTOCOL; } | IPFY_ICMPC_PORUNR { $$ = ICMP_UNREACH_PORT; } | IPFY_ICMPC_NEEDF { $$ = ICMP_UNREACH_NEEDFRAG; } | IPFY_ICMPC_SRCFAIL { $$ = ICMP_UNREACH_SRCFAIL; } | IPFY_ICMPC_NETUNK { $$ = ICMP_UNREACH_NET_UNKNOWN; } | IPFY_ICMPC_HSTUNK { $$ = ICMP_UNREACH_HOST_UNKNOWN; } | IPFY_ICMPC_ISOLATE { $$ = ICMP_UNREACH_ISOLATED; } | IPFY_ICMPC_NETPRO { $$ = ICMP_UNREACH_NET_PROHIB; } | IPFY_ICMPC_HSTPRO { $$ = ICMP_UNREACH_HOST_PROHIB; } | IPFY_ICMPC_NETTOS { $$ = ICMP_UNREACH_TOSNET; } | IPFY_ICMPC_HSTTOS { $$ = ICMP_UNREACH_TOSHOST; } | IPFY_ICMPC_FLTPRO { $$ = ICMP_UNREACH_ADMIN_PROHIBIT; } | IPFY_ICMPC_HSTPRE { $$ = 14; } | IPFY_ICMPC_CUTPRE { $$ = 15; } ; opt: IPFY_IPOPT_NOP { $$ = getoptbyvalue(IPOPT_NOP); } | IPFY_IPOPT_RR { $$ = getoptbyvalue(IPOPT_RR); } | IPFY_IPOPT_ZSU { $$ = getoptbyvalue(IPOPT_ZSU); } | IPFY_IPOPT_MTUP { $$ = getoptbyvalue(IPOPT_MTUP); } | IPFY_IPOPT_MTUR { $$ = getoptbyvalue(IPOPT_MTUR); } | IPFY_IPOPT_ENCODE { $$ = getoptbyvalue(IPOPT_ENCODE); } | IPFY_IPOPT_TS { $$ = getoptbyvalue(IPOPT_TS); } | IPFY_IPOPT_TR { $$ = getoptbyvalue(IPOPT_TR); } | 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 doi { $$ = getoptbyvalue(IPOPT_CIPSO); } | IPFY_IPOPT_SATID { $$ = getoptbyvalue(IPOPT_SATID); } | IPFY_IPOPT_SSRR { $$ = getoptbyvalue(IPOPT_SSRR); } | IPFY_IPOPT_ADDEXT { $$ = getoptbyvalue(IPOPT_ADDEXT); } | IPFY_IPOPT_VISA { $$ = getoptbyvalue(IPOPT_VISA); } | IPFY_IPOPT_IMITD { $$ = getoptbyvalue(IPOPT_IMITD); } | IPFY_IPOPT_EIP { $$ = getoptbyvalue(IPOPT_EIP); } | IPFY_IPOPT_FINN { $$ = getoptbyvalue(IPOPT_FINN); } | IPFY_IPOPT_DPS { $$ = getoptbyvalue(IPOPT_DPS); } | IPFY_IPOPT_SDB { $$ = getoptbyvalue(IPOPT_SDB); } | IPFY_IPOPT_NSAPA { $$ = getoptbyvalue(IPOPT_NSAPA); } | IPFY_IPOPT_RTRALRT { $$ = getoptbyvalue(IPOPT_RTRALRT); } | 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; yyresetdict(); } ; setsecclass: 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: IPFY_AH { $$ = getv6optbyvalue(IPPROTO_AH); } | IPFY_IPV6OPT_DSTOPTS { $$ = getv6optbyvalue(IPPROTO_DSTOPTS); } | IPFY_IPV6OPT_ESP { $$ = getv6optbyvalue(IPPROTO_ESP); } | IPFY_IPV6OPT_HOPOPTS { $$ = getv6optbyvalue(IPPROTO_HOPOPTS); } | IPFY_IPV6OPT_IPV6 { $$ = getv6optbyvalue(IPPROTO_IPV6); } | IPFY_IPV6OPT_NONE { $$ = getv6optbyvalue(IPPROTO_NONE); } | IPFY_IPV6OPT_ROUTING { $$ = getv6optbyvalue(IPPROTO_ROUTING); } | IPFY_IPV6OPT_FRAG { $$ = getv6optbyvalue(IPPROTO_FRAGMENT); } | IPFY_IPV6OPT_MOBILITY { $$ = getv6optbyvalue(IPPROTO_MOBILITY); } ; level: IPFY_LEVEL { setsyslog(); } ; loglevel: priority { fr->fr_loglevel = LOG_LOCAL0|$1; } | facility '.' priority { fr->fr_loglevel = $1 | $3; } ; facility: IPFY_FAC_KERN { $$ = LOG_KERN; } | IPFY_FAC_USER { $$ = LOG_USER; } | IPFY_FAC_MAIL { $$ = LOG_MAIL; } | IPFY_FAC_DAEMON { $$ = LOG_DAEMON; } | IPFY_FAC_AUTH { $$ = LOG_AUTH; } | IPFY_FAC_SYSLOG { $$ = LOG_SYSLOG; } | IPFY_FAC_LPR { $$ = LOG_LPR; } | IPFY_FAC_NEWS { $$ = LOG_NEWS; } | IPFY_FAC_UUCP { $$ = LOG_UUCP; } | IPFY_FAC_CRON { $$ = LOG_CRON; } | IPFY_FAC_FTP { $$ = LOG_FTP; } | IPFY_FAC_AUTHPRIV { $$ = LOG_AUTHPRIV; } | IPFY_FAC_AUDIT { $$ = LOG_AUDIT; } | IPFY_FAC_LFMT { $$ = LOG_LFMT; } | IPFY_FAC_LOCAL0 { $$ = LOG_LOCAL0; } | IPFY_FAC_LOCAL1 { $$ = LOG_LOCAL1; } | IPFY_FAC_LOCAL2 { $$ = LOG_LOCAL2; } | IPFY_FAC_LOCAL3 { $$ = LOG_LOCAL3; } | IPFY_FAC_LOCAL4 { $$ = LOG_LOCAL4; } | IPFY_FAC_LOCAL5 { $$ = LOG_LOCAL5; } | IPFY_FAC_LOCAL6 { $$ = LOG_LOCAL6; } | IPFY_FAC_LOCAL7 { $$ = LOG_LOCAL7; } | IPFY_FAC_SECURITY { $$ = LOG_SECURITY; } ; priority: IPFY_PRI_EMERG { $$ = LOG_EMERG; } | IPFY_PRI_ALERT { $$ = LOG_ALERT; } | IPFY_PRI_CRIT { $$ = LOG_CRIT; } | IPFY_PRI_ERR { $$ = LOG_ERR; } | IPFY_PRI_WARN { $$ = LOG_WARNING; } | IPFY_PRI_NOTICE { $$ = LOG_NOTICE; } | IPFY_PRI_INFO { $$ = LOG_INFO; } | IPFY_PRI_DEBUG { $$ = LOG_DEBUG; } ; compare: YY_CMP_EQ { $$ = FR_EQUAL; } | YY_CMP_NE { $$ = FR_NEQUAL; } | YY_CMP_LT { $$ = FR_LESST; } | YY_CMP_LE { $$ = FR_LESSTE; } | YY_CMP_GT { $$ = FR_GREATERT; } | YY_CMP_GE { $$ = FR_GREATERTE; } ; range: YY_RANGE_IN { $$ = FR_INRANGE; } | YY_RANGE_OUT { $$ = FR_OUTRANGE; } | ':' { $$ = FR_INCRANGE; } ; servicename: YY_STR { $$ = $1; } ; interfacename: name { $$ = $1; } | name ':' YY_NUMBER { $$ = $1; fprintf(stderr, "%d: Logical interface %s:%d unsupported, " "use the physical interface %s instead.\n", yylineNum, $1, $3, $1); } ; name: YY_STR { $$ = $1; } | '-' { $$ = strdup("-"); } ; ipv4_16: YY_NUMBER '.' YY_NUMBER { if ($1 > 255 || $3 > 255) { yyerror("Invalid octet string for IP address"); - return 0; + return(0); } $$.s_addr = ($1 << 24) | ($3 << 16); $$.s_addr = htonl($$.s_addr); } ; ipv4_24: ipv4_16 '.' YY_NUMBER { if ($3 > 255) { yyerror("Invalid octet string for IP address"); - return 0; + return(0); } $$.s_addr |= htonl($3 << 8); } ; ipv4: ipv4_24 '.' YY_NUMBER { if ($3 > 255) { yyerror("Invalid octet string for IP address"); - return 0; + return(0); } $$.s_addr |= htonl($3); } | ipv4_24 | ipv4_16 ; %% static struct wordtab ipfwords[] = { { "age", IPFY_AGE }, { "ah", IPFY_AH }, { "all", IPFY_ALL }, { "and", IPFY_AND }, { "auth", IPFY_AUTH }, { "bad", IPFY_BAD }, { "bad-nat", IPFY_BADNAT }, { "bad-src", IPFY_BADSRC }, { "bcast", IPFY_BROADCAST }, { "block", IPFY_BLOCK }, { "body", IPFY_BODY }, { "bpf-v4", IPFY_BPFV4 }, #ifdef USE_INET6 { "bpf-v6", IPFY_BPFV6 }, #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 }, { "frag", IPFY_FRAG }, { "frag-body", IPFY_FRAGBODY }, { "frags", IPFY_FRAGS }, { "from", IPFY_FROM }, { "ge", YY_CMP_GE }, { "group", IPFY_GROUP }, { "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 }, { "nat", IPFY_NAT }, { "ne", YY_CMP_NE }, { "net", IPFY_NETWORK }, { "newisn", IPFY_NEWISN }, { "no", IPFY_NO }, { "no-icmp-err", IPFY_NOICMPERR }, { "nolog", IPFY_NOLOG }, { "nomatch", IPFY_NOMATCH }, { "now", IPFY_NOW }, { "not", IPFY_NOT }, { "oow", IPFY_OOW }, { "on", IPFY_ON }, { "opt", IPFY_OPT }, { "or-block", IPFY_ORBLOCK }, { "out", IPFY_OUT }, { "out-via", IPFY_OUTVIA }, { "pass", IPFY_PASS }, { "port", IPFY_PORT }, { "pps", IPFY_PPS }, { "preauth", IPFY_PREAUTH }, { "proto", IPFY_PROTO }, { "quick", IPFY_QUICK }, { "reply-to", IPFY_REPLY_TO }, { "return-icmp", IPFY_RETICMP }, { "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 }, { "state", IPFY_STATE }, { "state-age", IPFY_AGE }, { "strict", IPFY_STRICT }, { "sync", IPFY_SYNC }, { "tcp", IPFY_TCP }, { "tcp-udp", IPFY_TCPUDP }, { "tos", IPFY_TOS }, { "to", IPFY_TO }, { "ttl", IPFY_TTL }, { "udp", IPFY_UDP }, { "v6hdr", IPFY_V6HDR }, { "v6hdrs", IPFY_V6HDRS }, { "with", IPFY_WITH }, { NULL, 0 } }; static struct wordtab addrwords[] = { { "any", IPFY_ANY }, { "hash", IPFY_HASH }, { "pool", IPFY_POOL }, { NULL, 0 } }; static struct wordtab maskwords[] = { { "broadcast", IPFY_BROADCAST }, { "netmasked", IPFY_NETMASKED }, { "network", IPFY_NETWORK }, { "peer", IPFY_PEER }, { NULL, 0 } }; static struct wordtab icmpcodewords[] = { { "cutoff-preced", IPFY_ICMPC_CUTPRE }, { "filter-prohib", IPFY_ICMPC_FLTPRO }, { "isolate", IPFY_ICMPC_ISOLATE }, { "needfrag", IPFY_ICMPC_NEEDF }, { "net-prohib", IPFY_ICMPC_NETPRO }, { "net-tos", IPFY_ICMPC_NETTOS }, { "host-preced", IPFY_ICMPC_HSTPRE }, { "host-prohib", IPFY_ICMPC_HSTPRO }, { "host-tos", IPFY_ICMPC_HSTTOS }, { "host-unk", IPFY_ICMPC_HSTUNK }, { "host-unr", IPFY_ICMPC_HSTUNR }, { "net-unk", IPFY_ICMPC_NETUNK }, { "net-unr", IPFY_ICMPC_NETUNR }, { "port-unr", IPFY_ICMPC_PORUNR }, { "proto-unr", IPFY_ICMPC_PROUNR }, { "srcfail", IPFY_ICMPC_SRCFAIL }, { NULL, 0 }, }; static struct wordtab ipv4optwords[] = { { "addext", IPFY_IPOPT_ADDEXT }, { "cipso", IPFY_IPOPT_CIPSO }, { "dps", IPFY_IPOPT_DPS }, { "e-sec", IPFY_IPOPT_ESEC }, { "eip", IPFY_IPOPT_EIP }, { "encode", IPFY_IPOPT_ENCODE }, { "finn", IPFY_IPOPT_FINN }, { "imitd", IPFY_IPOPT_IMITD }, { "lsrr", IPFY_IPOPT_LSRR }, { "mtup", IPFY_IPOPT_MTUP }, { "mtur", IPFY_IPOPT_MTUR }, { "nop", IPFY_IPOPT_NOP }, { "nsapa", IPFY_IPOPT_NSAPA }, { "rr", IPFY_IPOPT_RR }, { "rtralrt", IPFY_IPOPT_RTRALRT }, { "satid", IPFY_IPOPT_SATID }, { "sdb", IPFY_IPOPT_SDB }, { "sec", IPFY_IPOPT_SEC }, { "ssrr", IPFY_IPOPT_SSRR }, { "tr", IPFY_IPOPT_TR }, { "ts", IPFY_IPOPT_TS }, { "ump", IPFY_IPOPT_UMP }, { "visa", IPFY_IPOPT_VISA }, { "zsu", IPFY_IPOPT_ZSU }, { NULL, 0 }, }; static struct wordtab ipv4secwords[] = { { "confid", IPFY_SEC_CONF }, { "reserv-1", IPFY_SEC_RSV1 }, { "reserv-2", IPFY_SEC_RSV2 }, { "reserv-3", IPFY_SEC_RSV3 }, { "reserv-4", IPFY_SEC_RSV4 }, { "secret", IPFY_SEC_SEC }, { "topsecret", IPFY_SEC_TS }, { "unclass", IPFY_SEC_UNC }, { NULL, 0 }, }; static struct wordtab ipv6optwords[] = { { "dstopts", IPFY_IPV6OPT_DSTOPTS }, { "esp", IPFY_IPV6OPT_ESP }, { "frag", IPFY_IPV6OPT_FRAG }, { "hopopts", IPFY_IPV6OPT_HOPOPTS }, { "ipv6", IPFY_IPV6OPT_IPV6 }, { "mobility", IPFY_IPV6OPT_MOBILITY }, { "none", IPFY_IPV6OPT_NONE }, { "routing", IPFY_IPV6OPT_ROUTING }, { NULL, 0 }, }; static struct wordtab logwords[] = { { "kern", IPFY_FAC_KERN }, { "user", IPFY_FAC_USER }, { "mail", IPFY_FAC_MAIL }, { "daemon", IPFY_FAC_DAEMON }, { "auth", IPFY_FAC_AUTH }, { "syslog", IPFY_FAC_SYSLOG }, { "lpr", IPFY_FAC_LPR }, { "news", IPFY_FAC_NEWS }, { "uucp", IPFY_FAC_UUCP }, { "cron", IPFY_FAC_CRON }, { "ftp", IPFY_FAC_FTP }, { "authpriv", IPFY_FAC_AUTHPRIV }, { "audit", IPFY_FAC_AUDIT }, { "logalert", IPFY_FAC_LFMT }, { "console", IPFY_FAC_CONSOLE }, { "security", IPFY_FAC_SECURITY }, { "local0", IPFY_FAC_LOCAL0 }, { "local1", IPFY_FAC_LOCAL1 }, { "local2", IPFY_FAC_LOCAL2 }, { "local3", IPFY_FAC_LOCAL3 }, { "local4", IPFY_FAC_LOCAL4 }, { "local5", IPFY_FAC_LOCAL5 }, { "local6", IPFY_FAC_LOCAL6 }, { "local7", IPFY_FAC_LOCAL7 }, { "emerg", IPFY_PRI_EMERG }, { "alert", IPFY_PRI_ALERT }, { "crit", IPFY_PRI_CRIT }, { "err", IPFY_PRI_ERR }, { "warn", IPFY_PRI_WARN }, { "notice", IPFY_PRI_NOTICE }, { "info", IPFY_PRI_INFO }, { "debug", IPFY_PRI_DEBUG }, { NULL, 0 }, }; int ipf_parsefile(int fd, addfunc_t addfunc, ioctlfunc_t *iocfuncs, char *filename) { FILE *fp = NULL; char *s; yylineNum = 1; yysettab(ipfwords); s = getenv("YYDEBUG"); if (s != NULL) yydebug = atoi(s); else yydebug = 0; if (strcmp(filename, "-")) { fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "fopen(%s) failed: %s\n", filename, STRERROR(errno)); - return -1; + return(-1); } } else fp = stdin; while (ipf_parsesome(fd, addfunc, iocfuncs, fp) == 1) ; if (fp != NULL) fclose(fp); - return 0; + return(0); } int ipf_parsesome(int fd, addfunc_t addfunc, ioctlfunc_t *iocfuncs, FILE *fp) { char *s; int i; ipffd = fd; for (i = 0; i <= IPL_LOGMAX; i++) ipfioctls[i] = iocfuncs[i]; ipfaddfunc = addfunc; if (feof(fp)) - return 0; + return(0); i = fgetc(fp); if (i == EOF) - return 0; + return(0); if (ungetc(i, fp) == 0) - return 0; + return(0); if (feof(fp)) - return 0; + return(0); s = getenv("YYDEBUG"); if (s != NULL) yydebug = atoi(s); else yydebug = 0; yyin = fp; yyparse(); - return 1; + return(1); } static void newrule(void) { frentry_t *frn; frn = allocfr(); for (fr = frtop; fr != NULL && fr->fr_next != NULL; fr = fr->fr_next) ; if (fr != NULL) { fr->fr_next = frn; 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; 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; } static void setipftype(void) { for (fr = frc; fr != NULL; fr = fr->fr_next) { if (fr->fr_type == FR_T_NONE) { fr->fr_type = FR_T_IPF; fr->fr_data = (void *)calloc(sizeof(fripf_t), 1); fr->fr_dsize = sizeof(fripf_t); 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; } if (fr->fr_type != FR_T_IPF) { fprintf(stderr, "IPF Type not set\n"); } } } static frentry_t * addrule(void) { frentry_t *f, *f1, *f2; int count; for (f2 = frc; f2->fr_next != NULL; f2 = f2->fr_next) ; count = nrules; f = f2; for (f1 = frc; count > 0; count--, f1 = f1->fr_next) { f->fr_next = allocfr(); if (f->fr_next == NULL) - return NULL; + return(NULL); f->fr_next->fr_pnext = &f->fr_next; added++; f = f->fr_next; *f = *f1; f->fr_next = NULL; if (f->fr_caddr != NULL) { f->fr_caddr = malloc(f->fr_dsize); bcopy(f1->fr_caddr, f->fr_caddr, f->fr_dsize); } } - return f2->fr_next; + return(f2->fr_next); } static int lookuphost(char *name, i6addr_t *addrp) { int i; hashed = 0; pooled = 0; dynamic = -1; for (i = 0; i < 4; i++) { if (fr->fr_ifnames[i] == -1) continue; if (strcmp(name, fr->fr_names + fr->fr_ifnames[i]) == 0) { ifpflag = FRI_DYNAMIC; dynamic = addname(&fr, name); - return 1; + return(1); } } if (gethost(AF_INET, name, addrp) == -1) { fprintf(stderr, "unknown name \"%s\"\n", name); - return -1; + return(-1); } - return 0; + return(0); } static void dobpf(int v, char *phrase) { #ifdef IPFILTER_BPF struct bpf_program bpf; struct pcap *p; #endif fakebpf_t *fb; u_32_t l; char *s; int i; for (fr = frc; fr != NULL; fr = fr->fr_next) { if (fr->fr_type != FR_T_NONE) { fprintf(stderr, "cannot mix IPF and BPF matching\n"); return; } fr->fr_family = vtof(v); fr->fr_type = FR_T_BPFOPC; if (!strncmp(phrase, "0x", 2)) { fb = malloc(sizeof(fakebpf_t)); for (i = 0, s = strtok(phrase, " \r\n\t"); s != NULL; s = strtok(NULL, " \r\n\t"), i++) { fb = reallocarray(fb, i / 4 + 1, sizeof(*fb)); if (fb == NULL) { warnx("memory allocation error at %d in %s in %s", __LINE__, __FUNCTION__, __FILE__); abort(); } l = (u_32_t)strtol(s, NULL, 0); switch (i & 3) { case 0 : fb[i / 4].fb_c = l & 0xffff; break; case 1 : fb[i / 4].fb_t = l & 0xff; break; case 2 : fb[i / 4].fb_f = l & 0xff; break; case 3 : fb[i / 4].fb_k = l; break; } } if ((i & 3) != 0) { fprintf(stderr, "Odd number of bytes in BPF code\n"); exit(1); } i--; fr->fr_dsize = (i / 4 + 1) * sizeof(*fb); fr->fr_data = fb; return; } #ifdef IPFILTER_BPF bzero((char *)&bpf, sizeof(bpf)); p = pcap_open_dead(DLT_RAW, 1); if (!p) { fprintf(stderr, "pcap_open_dead failed\n"); return; } if (pcap_compile(p, &bpf, phrase, 1, 0xffffffff)) { pcap_perror(p, "ipf"); pcap_close(p); fprintf(stderr, "pcap parsing failed (%s)\n", phrase); return; } pcap_close(p); fr->fr_dsize = bpf.bf_len * sizeof(struct bpf_insn); fr->fr_data = malloc(fr->fr_dsize); bcopy((char *)bpf.bf_insns, fr->fr_data, fr->fr_dsize); if (!bpf_validate(fr->fr_data, bpf.bf_len)) { fprintf(stderr, "BPF validation failed\n"); return; } #endif } #ifdef IPFILTER_BPF if (opts & OPT_DEBUG) bpf_dump(&bpf, 0); #else fprintf(stderr, "BPF filter expressions not supported\n"); exit(1); #endif } static void resetaddr(void) { hashed = 0; pooled = 0; dynamic = -1; } static alist_t * newalist(alist_t *ptr) { alist_t *al; al = malloc(sizeof(*al)); if (al == NULL) - return NULL; + return(NULL); al->al_not = 0; al->al_next = ptr; - return al; + return(al); } static int makepool(alist_t *list) { ip_pool_node_t *n, *top; ip_pool_t pool; alist_t *a; int num; if (list == NULL) - return 0; + return(0); top = calloc(1, sizeof(*top)); if (top == NULL) - return 0; + return(0); for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { if (use_inet6 == 1) { #ifdef USE_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)); n = n->ipn_next; } } bzero((char *)&pool, sizeof(pool)); pool.ipo_unit = IPL_LOGIPF; pool.ipo_list = top; num = load_pool(&pool, ipfioctls[IPL_LOGLOOKUP]); while ((n = top) != NULL) { top = n->ipn_next; free(n); } - return num; + return(num); } static u_int makehash(alist_t *list) { iphtent_t *n, *top; iphtable_t iph; alist_t *a; int num; if (list == NULL) - return 0; + return(0); top = calloc(1, sizeof(*top)); if (top == NULL) - return 0; + return(0); for (n = top, a = list; (n != NULL) && (a != NULL); a = a->al_next) { 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)); n = n->ipe_next; } } bzero((char *)&iph, sizeof(iph)); iph.iph_unit = IPL_LOGIPF; iph.iph_type = IPHASH_LOOKUP; *iph.iph_name = '\0'; if (load_hash(&iph, top, ipfioctls[IPL_LOGLOOKUP]) == 0) sscanf(iph.iph_name, "%u", &num); else num = 0; while ((n = top) != NULL) { top = n->ipe_next; free(n); } - return num; + return(num); } int ipf_addrule(int fd, ioctlfunc_t ioctlfunc, void *ptr) { ioctlcmd_t add, del; frentry_t *fr; ipfobj_t obj; if (ptr == NULL) - return 0; + return(0); fr = ptr; add = 0; del = 0; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = fr->fr_size; obj.ipfo_type = IPFOBJ_FRENTRY; obj.ipfo_ptr = ptr; if ((opts & OPT_DONOTHING) != 0) fd = -1; if (opts & OPT_ZERORULEST) { add = SIOCZRLST; } else if (opts & OPT_INACTIVE) { add = (u_int)fr->fr_hits ? SIOCINIFR : SIOCADIFR; del = SIOCRMIFR; } else { add = (u_int)fr->fr_hits ? SIOCINAFR : SIOCADAFR; del = SIOCRMAFR; } if ((opts & OPT_OUTQUE) != 0) fr->fr_flags |= FR_OUTQUE; if (fr->fr_hits) fr->fr_hits--; if ((opts & OPT_VERBOSE) != 0) printfr(fr, ioctlfunc); if ((opts & OPT_DEBUG) != 0) { binprint(fr, sizeof(*fr)); if (fr->fr_data != NULL) binprint(fr->fr_data, fr->fr_dsize); } if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(zero rule)", fr->fr_flineno); - return ipf_perror_fd(fd, ioctlfunc, msg); + 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); #else printf("hits %ld bytes %ld ", fr->fr_hits, fr->fr_bytes); #endif printfr(fr, ioctlfunc); } } else if ((opts & OPT_REMOVE) != 0) { if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(delete rule)", fr->fr_flineno); - return ipf_perror_fd(fd, ioctlfunc, msg); + return(ipf_perror_fd(fd, ioctlfunc, msg)); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(add/insert rule)", fr->fr_flineno); - return ipf_perror_fd(fd, ioctlfunc, msg); + return(ipf_perror_fd(fd, ioctlfunc, msg)); } } } - return 0; + return(0); } static void setsyslog(void) { yysetdict(logwords); yybreakondot = 1; } static void unsetsyslog(void) { yyresetdict(); yybreakondot = 0; } static void fillgroup(frentry_t *fr) { frentry_t *f; 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; /* * Only copy down matching fields if the rules are of the same type * and are of ipf type. The only fields that are copied are those * that impact the rule parsing itself, eg. need for knowing what the * protocol should be for rules with port comparisons in them. */ if (f->fr_type != fr->fr_type || f->fr_type != FR_T_IPF) return; 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; if (fr->fr_proto == 0 && f->fr_proto != 0) fr->fr_proto = f->fr_proto; if ((fr->fr_mproto == 0) && ((fr->fr_flx & FI_TCPUDP) == 0) && ((f->fr_flx & FI_TCPUDP) != 0)) { fr->fr_flx |= FI_TCPUDP; fr->fr_mflx |= FI_TCPUDP; } } static void doipfexpr(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(char *varname, int value) { char buffer[80]; strncpy(buffer, varname, 60); buffer[59] = '\0'; strcat(buffer, "="); snprintf(buffer, sizeof(buffer), "%u", value); ipf_dotuning(ipffd, buffer, ioctl); } static void do_tunestr(char *varname, char *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(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(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; + 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; + return(pos); } static frentry_t * allocfr(void) { 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; + return(fr); } static void setgroup(frentry_t **frp, char *name) { int pos; pos = addname(frp, name); if (pos == -1) return; (*frp)->fr_group = pos; } static void setgrhead(frentry_t **frp, char *name) { int pos; pos = addname(frp, name); if (pos == -1) return; (*frp)->fr_grhead = pos; } static void seticmphead(frentry_t **frp, char *name) { int pos; pos = addname(frp, name); if (pos == -1) return; (*frp)->fr_icmphead = pos; } static void build_dstaddr_af(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(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/sbin/ipf/common/lexer.c b/sbin/ipf/common/lexer.c index bb401612ad9d..e84181356da4 100644 --- a/sbin/ipf/common/lexer.c +++ b/sbin/ipf/common/lexer.c @@ -1,737 +1,737 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include "ipf.h" #ifdef IPFILTER_SCAN # include "netinet/ip_scan.h" #endif #include #include #ifdef TEST_LEXER # define NO_YACC union { int num; char *str; struct in_addr ipa; i6addr_t ip6; } yylval; #endif #include "lexer.h" #include "y.tab.h" FILE *yyin; #define ishex(c) (ISDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || \ ((c) >= 'A' && (c) <= 'F')) #define TOOLONG -3 extern int string_start; extern int string_end; extern char *string_val; extern int pos; extern int yydebug; char *yystr = NULL; int yytext[YYBUFSIZ+1]; 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; int yytokentype = 0; wordtab_t *yywordtab = NULL; int yysavedepth = 0; wordtab_t *yysavewords[30]; static wordtab_t *yyfindkey(char *); static int yygetc(int); static void yyunputc(int); static int yyswallow(int); static char *yytexttostr(int, int); static void yystrtotext(char *); static char *yytexttochar(void); static int yygetc(int docont) { int c; if (yypos < yylast) { c = yytext[yypos++]; if (c == '\n') yylineNum++; - return c; + return(c); } if (yypos == YYBUFSIZ) - return TOOLONG; + return(TOOLONG); if (pos >= string_start && pos <= string_end) { c = string_val[pos - string_start]; yypos++; } else { c = fgetc(yyin); if (docont && (c == '\\')) { c = fgetc(yyin); if (c == '\n') { yylineNum++; c = fgetc(yyin); } } } if (c == '\n') yylineNum++; yytext[yypos++] = c; yylast = yypos; yytext[yypos] = '\0'; - return c; + return(c); } static void yyunputc(int c) { if (c == '\n') yylineNum--; yytext[--yypos] = c; } static int yyswallow(int last) { int c; while (((c = yygetc(0)) > '\0') && (c != last)) ; if (c != EOF) yyunputc(c); if (c == last) - return 0; - return -1; + return(0); + return(-1); } static char * yytexttochar(void) { int i; for (i = 0; i < yypos; i++) yychars[i] = (char)(yytext[i] & 0xff); yychars[i] = '\0'; - return yychars; + return(yychars); } static void yystrtotext(char *str) { int len; char *s; len = strlen(str); if (len > YYBUFSIZ) len = YYBUFSIZ; for (s = str; *s != '\0' && len > 0; s++, len--) yytext[yylast++] = *s; yytext[yylast] = '\0'; } static char * yytexttostr(int offset, int max) { char *str; int i; if ((yytext[offset] == '\'' || yytext[offset] == '"') && (yytext[offset] == yytext[offset + max - 1])) { offset++; max--; } if (max > yylast) max = yylast; str = malloc(max + 1); if (str != NULL) { for (i = offset; i < max; i++) str[i - offset] = (char)(yytext[i] & 0xff); str[i - offset] = '\0'; } - return str; + return(str); } int yylex(void) { 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; rval = 0; if (yystr != NULL) { free(yystr); yystr = NULL; } nextchar: c = yygetc(0); if (yydebug > 1) printf("yygetc = (%x) %c [%*.*s]\n", c, c, yypos, yypos, yytexttochar()); switch (c) { case '\n' : lnext = 0; nokey = 0; case '\t' : case '\r' : case ' ' : if (isbuilding == 1) { yyunputc(c); goto done; } if (yylast > yypos) { bcopy(yytext + yypos, yytext, sizeof(yytext[0]) * (yylast - yypos + 1)); } yylast -= yypos; if (yyexpectaddr == 2) yyexpectaddr = 0; yypos = 0; lnext = 0; nokey = 0; goto nextchar; case '\\' : if (lnext == 0) { lnext = 1; if (yylast == yypos) { yylast--; yypos--; } else yypos--; if (yypos == 0) nokey = 1; goto nextchar; } break; } if (lnext == 1) { lnext = 0; if ((isbuilding == 0) && !ISALNUM(c)) { prior = c; - return c; + return(c); } goto nextchar; } switch (c) { case '#' : if (isbuilding == 1) { yyunputc(c); goto done; } yyswallow('\n'); rval = YY_COMMENT; goto done; case '$' : if (isbuilding == 1) { yyunputc(c); goto done; } n = yygetc(0); if (n == '{') { if (yyswallow('}') == -1) { rval = -2; goto done; } (void) yygetc(0); } else { if (!ISALPHA(n)) { yyunputc(n); break; } do { n = yygetc(1); } while (ISALPHA(n) || ISDIGIT(n) || n == '_'); yyunputc(n); } name = yytexttostr(1, yypos); /* skip $ */ if (name != NULL) { string_val = get_variable(name, NULL, yylineNum); free(name); if (string_val != NULL) { name = yytexttostr(yypos, yylast); if (name != NULL) { yypos = 0; yylast = 0; yystrtotext(string_val); yystrtotext(name); free(string_val); free(name); goto nextchar; } free(string_val); } } break; case '\'': case '"' : if (isbuilding == 1) { goto done; } do { n = yygetc(1); if (n == EOF || n == TOOLONG) { rval = -2; goto done; } if (n == '\n') { yyunputc(' '); yypos++; } } while (n != c); rval = YY_STR; goto done; /* NOTREACHED */ case EOF : yylineNum = 1; yypos = 0; yylast = -1; yyexpectaddr = 0; yybreakondot = 0; yyvarnext = 0; yytokentype = 0; if (yydebug) fprintf(stderr, "reset at EOF\n"); prior = 0; - return 0; + return(0); } if (strchr("=,/;{}()@", c) != NULL) { if (isbuilding == 1) { yyunputc(c); goto done; } rval = c; goto done; } else if (c == '.') { if (isbuilding == 0) { rval = c; goto done; } if (yybreakondot != 0) { yyunputc(c); goto done; } } switch (c) { case '-' : 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; case '!' : if (isbuilding == 1) { yyunputc(c); goto done; } n = yygetc(0); if (n == '=') { rval = YY_CMP_NE; goto done; } yyunputc(n); rval = '!'; goto done; case '<' : if (yyexpectaddr) break; if (isbuilding == 1) { yyunputc(c); goto done; } n = yygetc(0); if (n == '=') { rval = YY_CMP_LE; goto done; } if (n == '>') { rval = YY_RANGE_OUT; goto done; } yyunputc(n); rval = YY_CMP_LT; goto done; case '>' : if (yyexpectaddr) break; if (isbuilding == 1) { yyunputc(c); goto done; } n = yygetc(0); if (n == '=') { rval = YY_CMP_GE; goto done; } if (n == '<') { rval = YY_RANGE_IN; goto done; } yyunputc(n); rval = YY_CMP_GT; goto done; } /* * Now for the reason this is here...IPv6 address parsing. * The longest string we can expect is of this form: * 0000:0000:0000:0000:0000:0000:000.000.000.000 * not: * 0000:0000:0000:0000:0000:0000:0000:0000 */ #ifdef USE_INET6 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 == ':') { snprintf(s, sizeof(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 * the code in inet_pton() anyway. */ do { *s++ = c; c = yygetc(1); } while ((ishex(c) || c == ':' || c == '.') && (s - ipv6buf < 46)); yyunputc(c); *s = '\0'; if (inet_pton(AF_INET6, ipv6buf, &yylval.ip6) == 1) { rval = YY_IPV6; yyexpectaddr = 0; goto done; } yypos = start; c = oc; } #endif 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; } rval = ':'; goto done; } if (isbuilding == 0 && c == '0') { n = yygetc(0); if (n == 'x') { do { n = yygetc(1); } while (ishex(n)); yyunputc(n); rval = YY_HEX; goto done; } yyunputc(n); } /* * No negative numbers with leading - sign.. */ if (isbuilding == 0 && ISDIGIT(c)) { do { n = yygetc(1); } while (ISDIGIT(n)); yyunputc(n); rval = YY_NUMBER; goto done; } isbuilding = 1; goto nextchar; done: yystr = yytexttostr(0, yypos); if (yydebug) printf("isbuilding %d yyvarnext %d nokey %d fixed %d addr %d\n", isbuilding, yyvarnext, nokey, yydictfixed, yyexpectaddr); if (isbuilding == 1) { wordtab_t *w; w = NULL; isbuilding = 0; if ((yyvarnext == 0) && (nokey == 0)) { w = yyfindkey(yystr); if (w == NULL && yywordtab != NULL && !yydictfixed) { yyresetdict(); w = yyfindkey(yystr); } } else yyvarnext = 0; if (w != NULL) rval = w->w_value; else rval = YY_STR; } 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,%d] => %d @%d\n", yystr, isbuilding, yyexpectaddr, yysavedepth, string_start, string_end, pos, rval, yysavedepth); switch (rval) { case YY_NUMBER : sscanf(yystr, "%u", &yylval.num); break; case YY_HEX : sscanf(yystr, "0x%x", (u_int *)&yylval.num); break; case YY_STR : yylval.str = strdup(yystr); break; default : break; } if (yylast > 0) { bcopy(yytext + yypos, yytext, sizeof(yytext[0]) * (yylast - yypos + 1)); yylast -= yypos; yypos = 0; } if (rval == YY_NUMBER) priornum = yylval.num; prior = rval; - return rval; + return(rval); } static wordtab_t *yyfindkey(key) char *key; { wordtab_t *w; if (yywordtab == NULL) - return NULL; + return(NULL); for (w = yywordtab; w->w_word != 0; w++) if (strcasecmp(key, w->w_word) == 0) - return w; - return NULL; + return(w); + return(NULL); } char * yykeytostr(int num) { wordtab_t *w; if (yywordtab == NULL) - return ""; + return(""); for (w = yywordtab; w->w_word; w++) if (w->w_value == num) - return w->w_word; - return ""; + return(w->w_word); + return(""); } wordtab_t * yysettab(wordtab_t *words) { wordtab_t *save; save = yywordtab; yywordtab = words; - return save; + return(save); } void yyerror(char *msg) { char *txt, letter[2]; int freetxt = 0; if (yytokentype < 256) { letter[0] = yytokentype; letter[1] = '\0'; txt = letter; } else if (yytokentype == YY_STR || yytokentype == YY_HEX || yytokentype == YY_NUMBER) { if (yystr == NULL) { txt = yytexttostr(yypos, YYBUFSIZ); freetxt = 1; } else txt = yystr; } else { txt = yykeytostr(yytokentype); } fprintf(stderr, "%s error at \"%s\", line %d\n", msg, txt, yylineNum); if (freetxt == 1) free(txt); exit(1); } void yysetfixeddict(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(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); return; } yysavewords[yysavedepth++] = yysettab(newdict); if (yydebug) printf("yysavedepth++ => %d\n", yysavedepth); } void yyresetdict(void) { if (yydebug) printf("yyresetdict(%d)\n", yysavedepth); if (yysavedepth > 0) { yysettab(yysavewords[--yysavedepth]); if (yydebug) printf("yysavedepth-- => %d\n", yysavedepth); } yydictfixed = 0; } #ifdef TEST_LEXER int main(int argc, char *argv[]) { int n; yyin = stdin; while ((n = yylex()) != 0) printf("%d.n = %d [%s] %d %d\n", yylineNum, n, yystr, yypos, yylast); } #endif diff --git a/sbin/ipf/ipf/bpf_filter.c b/sbin/ipf/ipf/bpf_filter.c index 85a38a88bf57..32d144b492ce 100644 --- a/sbin/ipf/ipf/bpf_filter.c +++ b/sbin/ipf/ipf/bpf_filter.c @@ -1,595 +1,595 @@ /* $FreeBSD$ */ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)bpf.c 7.5 (Berkeley) 7/15/91 */ #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) static const char rcsid[] = "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.3 2006/10/03 11:25:56 darrenr Exp $ (LBL)"; #endif #include #include #include #include #include #include #include "netinet/ip_compat.h" #include "bpf-ipf.h" #if (defined(__hpux) || SOLARIS) && (defined(_KERNEL) || defined(KERNEL)) # include # include #endif #include "pcap-ipf.h" #if !defined(KERNEL) && !defined(_KERNEL) #include #endif #define int32 bpf_int32 #define u_int32 bpf_u_int32 static int m_xword(mb_t *, int, int *); static int m_xhalf(mb_t *, int, int *); #ifndef LBL_ALIGN /* * XXX - IA-64? If not, this probably won't work on Win64 IA-64 * systems, unless LBL_ALIGN is defined elsewhere for them. * XXX - SuperH? If not, this probably won't work on WinCE SuperH * systems, unless LBL_ALIGN is defined elsewhere for them. */ #if defined(sparc) || defined(__sparc__) || defined(mips) || \ defined(ibm032) || defined(__alpha) || defined(__hpux) || \ defined(__arm__) #define LBL_ALIGN #endif #endif #ifndef LBL_ALIGN #define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) #define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) #else #define EXTRACT_SHORT(p)\ ((u_short)\ ((u_short)*((u_char *)p+0)<<8|\ (u_short)*((u_char *)p+1)<<0)) #define EXTRACT_LONG(p)\ ((u_int32)*((u_char *)p+0)<<24|\ (u_int32)*((u_char *)p+1)<<16|\ (u_int32)*((u_char *)p+2)<<8|\ (u_int32)*((u_char *)p+3)<<0) #endif #define MINDEX(len, _m, _k) \ { \ len = M_LEN(m); \ while ((_k) >= len) { \ (_k) -= len; \ (_m) = (_m)->m_next; \ if ((_m) == 0) \ - return 0; \ + return(0); \ len = M_LEN(m); \ } \ } static int m_xword(m, k, err) register mb_t *m; register int k, *err; { register int len; register u_char *cp, *np; register mb_t *m0; MINDEX(len, m, k); cp = MTOD(m, u_char *) + k; if (len - k >= 4) { *err = 0; - return EXTRACT_LONG(cp); + return(EXTRACT_LONG(cp)); } m0 = m->m_next; if (m0 == NULL || M_LEN(m0) + len - k < 4) goto bad; *err = 0; np = MTOD(m0, u_char *); switch (len - k) { case 1: - return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; + return(cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; case 2: - return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; + return(cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; default: - return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; + return(cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; } bad: *err = 1; - return 0; + return(0); } static int m_xhalf(m, k, err) register mb_t *m; register int k, *err; { register int len; register u_char *cp; register mb_t *m0; MINDEX(len, m, k); cp = MTOD(m, u_char *) + k; if (len - k >= 2) { *err = 0; - return EXTRACT_SHORT(cp); + return(EXTRACT_SHORT(cp)); } m0 = m->m_next; if (m0 == NULL) goto bad; *err = 0; - return (cp[0] << 8) | MTOD(m0, u_char *)[0]; + return(cp[0] << 8) | MTOD(m0, u_char *)[0]; bad: *err = 1; - return 0; + return(0); } /* * Execute the filter program starting at pc on the packet p * wirelen is the length of the original packet * buflen is the amount of data present * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, * in all other cases, p is a pointer to a buffer and buflen is its size. */ u_int bpf_filter(pc, p, wirelen, buflen) register struct bpf_insn *pc; register u_char *p; u_int wirelen; register u_int buflen; { register u_int32 A, X; register int k; int32 mem[BPF_MEMWORDS]; mb_t *m, *n; int merr = 0; /* XXX: GCC */ int len; if (buflen == 0) { m = (mb_t *)p; p = MTOD(m, u_char *); buflen = M_LEN(m); } else m = NULL; if (pc == NULL) /* * No filter means accept all. */ - return (u_int)-1; + return(u_int)-1; A = 0; X = 0; --pc; while (1) { ++pc; switch (pc->code) { default: - return 0; + return(0); case BPF_RET|BPF_K: - return (u_int)pc->k; + return(u_int)pc->k; case BPF_RET|BPF_A: - return (u_int)A; + return(u_int)A; case BPF_LD|BPF_W|BPF_ABS: k = pc->k; if (k + sizeof(int32) > buflen) { if (m == NULL) - return 0; + return(0); A = m_xword(m, k, &merr); if (merr != 0) - return 0; + return(0); continue; } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_ABS: k = pc->k; if (k + sizeof(short) > buflen) { if (m == NULL) - return 0; + return(0); A = m_xhalf(m, k, &merr); if (merr != 0) - return 0; + return(0); continue; } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_ABS: k = pc->k; if (k >= buflen) { if (m == NULL) - return 0; + return(0); n = m; MINDEX(len, n, k); A = MTOD(n, u_char *)[k]; continue; } A = p[k]; continue; case BPF_LD|BPF_W|BPF_LEN: A = wirelen; continue; case BPF_LDX|BPF_W|BPF_LEN: X = wirelen; continue; case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; if (k + sizeof(int32) > buflen) { if (m == NULL) - return 0; + return(0); A = m_xword(m, k, &merr); if (merr != 0) - return 0; + return(0); continue; } A = EXTRACT_LONG(&p[k]); continue; case BPF_LD|BPF_H|BPF_IND: k = X + pc->k; if (k + sizeof(short) > buflen) { if (m == NULL) - return 0; + return(0); A = m_xhalf(m, k, &merr); if (merr != 0) - return 0; + return(0); continue; } A = EXTRACT_SHORT(&p[k]); continue; case BPF_LD|BPF_B|BPF_IND: k = X + pc->k; if (k >= buflen) { if (m == NULL) - return 0; + return(0); n = m; MINDEX(len, n, k); A = MTOD(n, u_char *)[k]; continue; } A = p[k]; continue; case BPF_LDX|BPF_MSH|BPF_B: k = pc->k; if (k >= buflen) { if (m == NULL) - return 0; + return(0); n = m; MINDEX(len, n, k); X = (MTOD(n, char *)[k] & 0xf) << 2; continue; } X = (p[pc->k] & 0xf) << 2; continue; case BPF_LD|BPF_IMM: A = pc->k; continue; case BPF_LDX|BPF_IMM: X = pc->k; continue; case BPF_LD|BPF_MEM: A = mem[pc->k]; continue; case BPF_LDX|BPF_MEM: X = mem[pc->k]; continue; case BPF_ST: mem[pc->k] = A; continue; case BPF_STX: mem[pc->k] = X; continue; case BPF_JMP|BPF_JA: pc += pc->k; continue; case BPF_JMP|BPF_JGT|BPF_K: pc += (A > pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_K: pc += (A >= pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_K: pc += (A == pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_K: pc += (A & pc->k) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGT|BPF_X: pc += (A > X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JGE|BPF_X: pc += (A >= X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JEQ|BPF_X: pc += (A == X) ? pc->jt : pc->jf; continue; case BPF_JMP|BPF_JSET|BPF_X: pc += (A & X) ? pc->jt : pc->jf; continue; case BPF_ALU|BPF_ADD|BPF_X: A += X; continue; case BPF_ALU|BPF_SUB|BPF_X: A -= X; continue; case BPF_ALU|BPF_MUL|BPF_X: A *= X; continue; case BPF_ALU|BPF_DIV|BPF_X: if (X == 0) - return 0; + return(0); A /= X; continue; case BPF_ALU|BPF_AND|BPF_X: A &= X; continue; case BPF_ALU|BPF_OR|BPF_X: A |= X; continue; case BPF_ALU|BPF_LSH|BPF_X: A <<= X; continue; case BPF_ALU|BPF_RSH|BPF_X: A >>= X; continue; case BPF_ALU|BPF_ADD|BPF_K: A += pc->k; continue; case BPF_ALU|BPF_SUB|BPF_K: A -= pc->k; continue; case BPF_ALU|BPF_MUL|BPF_K: A *= pc->k; continue; case BPF_ALU|BPF_DIV|BPF_K: A /= pc->k; continue; case BPF_ALU|BPF_AND|BPF_K: A &= pc->k; continue; case BPF_ALU|BPF_OR|BPF_K: A |= pc->k; continue; case BPF_ALU|BPF_LSH|BPF_K: A <<= pc->k; continue; case BPF_ALU|BPF_RSH|BPF_K: A >>= pc->k; continue; case BPF_ALU|BPF_NEG: A = -A; continue; case BPF_MISC|BPF_TAX: X = A; continue; case BPF_MISC|BPF_TXA: A = X; continue; } } } /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid * code, that memory accesses are within valid ranges (to the * extent that this can be checked statically; loads of packet * data have to be, and are, also checked at run time), and that * the code terminates with either an accept or reject. * * The kernel needs to be able to verify an application's filter code. * Otherwise, a bogus program could easily crash the system. */ int bpf_validate(f, len) struct bpf_insn *f; int len; { u_int i, from; const struct bpf_insn *p; if (len == 0) - return 1; + return(1); if (len < 1 || len > BPF_MAXINSNS) - return 0; + return(0); for (i = 0; i < len; ++i) { p = &f[i]; switch (BPF_CLASS(p->code)) { /* * Check that memory operations use valid addresses. */ case BPF_LD: case BPF_LDX: switch (BPF_MODE(p->code)) { case BPF_IMM: break; case BPF_ABS: case BPF_IND: case BPF_MSH: /* * More strict check with actual packet length * is done runtime. */ #if 0 if (p->k >= bpf_maxbufsize) - return 0; + return(0); #endif break; case BPF_MEM: if (p->k >= BPF_MEMWORDS) - return 0; + return(0); break; case BPF_LEN: break; default: - return 0; + return(0); } break; case BPF_ST: case BPF_STX: if (p->k >= BPF_MEMWORDS) - return 0; + return(0); break; case BPF_ALU: switch (BPF_OP(p->code)) { case BPF_ADD: case BPF_SUB: case BPF_OR: case BPF_AND: case BPF_LSH: case BPF_RSH: case BPF_NEG: break; case BPF_DIV: /* * Check for constant division by 0. */ if (BPF_RVAL(p->code) == BPF_K && p->k == 0) - return 0; + return(0); default: - return 0; + return(0); } break; case BPF_JMP: /* * Check that jumps are within the code block, * and that unconditional branches don't go * backwards as a result of an overflow. * Unconditional branches have a 32-bit offset, * so they could overflow; we check to make * sure they don't. Conditional branches have * an 8-bit offset, and the from address is <= * BPF_MAXINSNS, and we assume that BPF_MAXINSNS * is sufficiently small that adding 255 to it * won't overflow. * * We know that len is <= BPF_MAXINSNS, and we * assume that BPF_MAXINSNS is < the maximum size * of a u_int, so that i + 1 doesn't overflow. */ from = i + 1; switch (BPF_OP(p->code)) { case BPF_JA: if (from + p->k < from || from + p->k >= len) - return 0; + return(0); break; case BPF_JEQ: case BPF_JGT: case BPF_JGE: case BPF_JSET: if (from + p->jt >= len || from + p->jf >= len) - return 0; + return(0); break; default: - return 0; + return(0); } break; case BPF_RET: break; case BPF_MISC: break; default: - return 0; + return(0); } } - return BPF_CLASS(f[len - 1].code) == BPF_RET; + return(BPF_CLASS(f[len - 1].code) == BPF_RET); } diff --git a/sbin/ipf/ipf/ipf.4 b/sbin/ipf/ipf/ipf.4 index 73a17a0cc8d3..559e48a3c6a5 100644 --- a/sbin/ipf/ipf/ipf.4 +++ b/sbin/ipf/ipf/ipf.4 @@ -1,254 +1,254 @@ .\" $FreeBSD$ .TH IPF 4 .SH NAME ipf \- packet filtering kernel interface .SH SYNOPSIS #include .br #include .SH IOCTLS .PP To add and delete rules to the filter list, three 'basic' ioctls are provided for use. The ioctl's are called as: .LP .nf ioctl(fd, SIOCADDFR, struct frentry **) ioctl(fd, SIOCDELFR, struct frentry **) ioctl(fd, SIOCIPFFL, int *) .fi .PP However, the full complement is as follows: .LP .nf ioctl(fd, SIOCADAFR, struct frentry **) (same as SIOCADDFR) ioctl(fd, SIOCRMAFR, struct frentry **) (same as SIOCDELFR) ioctl(fd, SIOCADIFR, struct frentry **) ioctl(fd, SIOCRMIFR, struct frentry **) ioctl(fd, SIOCINAFR, struct frentry **) ioctl(fd, SIOCINIFR, struct frentry **) ioctl(fd, SIOCSETFF, u_int *) ioctl(fd, SIOGGETFF, u_int *) ioctl(fd, SIOCGETFS, struct friostat **) ioctl(fd, SIOCIPFFL, int *) ioctl(fd, SIOCIPFFB, int *) ioctl(fd, SIOCSWAPA, u_int *) ioctl(fd, SIOCFRENB, u_int *) ioctl(fd, SIOCFRSYN, u_int *) ioctl(fd, SIOCFRZST, struct friostat **) ioctl(fd, SIOCZRLST, struct frentry **) ioctl(fd, SIOCAUTHW, struct fr_info **) ioctl(fd, SIOCAUTHR, struct fr_info **) ioctl(fd, SIOCATHST, struct fr_authstat **) .fi .PP The variations, SIOCADAFR vs. SIOCADIFR, allow operation on the two lists, active and inactive, respectively. All of these ioctl's are implemented as being routing ioctls and thus the same rules for the various routing ioctls and the file descriptor are employed, mainly being that the fd must be that of the device associated with the module (i.e., /dev/ipl). .PP The three groups of ioctls above perform adding rules to the end of the list (SIOCAD*), deletion of rules from any place in the list (SIOCRM*) and insertion of a rule into the list (SIOCIN*). The rule place into which it is inserted is stored in the "fr_hits" field, below. .LP .nf typedef struct frentry { struct frentry *fr_next; u_short fr_group; /* group to which this rule belongs */ u_short fr_grhead; /* group # which this rule starts */ struct frentry *fr_grp; int fr_ref; /* reference count - for grouping */ void *fr_ifa; #ifdef BSD void *fr_oifa; #endif /* * These are only incremented when a packet matches this rule and * it is the last match */ U_QUAD_T fr_hits; U_QUAD_T fr_bytes; /* * Fields after this may not change whilst in the kernel. */ struct fr_ip fr_ip; struct fr_ip fr_mip; /* mask structure */ u_char fr_tcpfm; /* tcp flags mask */ u_char fr_tcpf; /* tcp flags */ u_short fr_icmpm; /* data for ICMP packets (mask) */ u_short fr_icmp; u_char fr_scmp; /* data for port comparisons */ u_char fr_dcmp; u_short fr_dport; u_short fr_sport; u_short fr_stop; /* top port for <> and >< */ u_short fr_dtop; /* top port for <> and >< */ u_32_t fr_flags; /* per-rule flags && options (see below) */ u_short fr_skip; /* # of rules to skip */ u_short fr_loglevel; /* syslog log facility + priority */ int (*fr_func)(int, ip_t *, fr_info_t *)); - char fr_icode; /* return ICMP code */ +( char fr_icode; /* return ICMP code */); char fr_ifname[IFNAMSIZ]; #ifdef BSD char fr_oifname[IFNAMSIZ]; #endif struct frdest fr_tif; /* "to" interface */ struct frdest fr_dif; /* duplicate packet interfaces */ } frentry_t; .fi .PP When adding a new rule, all unused fields (in the filter rule) should be initialised to be zero. To insert a rule, at a particular position in the filter list, the number of the rule which it is to be inserted before must be put in the "fr_hits" field (the first rule is number 0). .PP Flags which are recognised in fr_flags: .nf FR_BLOCK 0x000001 /* do not allow packet to pass */ FR_PASS 0x000002 /* allow packet to pass */ FR_OUTQUE 0x000004 /* outgoing packets */ FR_INQUE 0x000008 /* ingoing packets */ FR_LOG 0x000010 /* Log */ FR_LOGB 0x000011 /* Log-fail */ FR_LOGP 0x000012 /* Log-pass */ FR_LOGBODY 0x000020 /* log the body of packets too */ FR_LOGFIRST 0x000040 /* log only the first packet to match */ - FR_RETRST 0x000080 /* return a TCP RST packet if blocked */ - FR_RETICMP 0x000100 /* return an ICMP packet if blocked */ +( FR_RETRST 0x000080 /* return a TCP RST packet if blocked */); +( FR_RETICMP 0x000100 /* return an ICMP packet if blocked */); FR_FAKEICMP 0x00180 /* Return ICMP unreachable with fake source */ FR_NOMATCH 0x000200 /* no match occured */ FR_ACCOUNT 0x000400 /* count packet bytes */ FR_KEEPFRAG 0x000800 /* keep fragment information */ FR_KEEPSTATE 0x001000 /* keep `connection' state information */ FR_INACTIVE 0x002000 FR_QUICK 0x004000 /* match & stop processing list */ FR_FASTROUTE 0x008000 /* bypass normal routing */ FR_CALLNOW 0x010000 /* call another function (fr_func) if matches */ FR_DUP 0x020000 /* duplicate the packet */ FR_LOGORBLOCK 0x040000 /* block the packet if it can't be logged */ FR_NOTSRCIP 0x080000 /* not the src IP# */ FR_NOTDSTIP 0x100000 /* not the dst IP# */ FR_AUTH 0x200000 /* use authentication */ FR_PREAUTH 0x400000 /* require preauthentication */ .fi .PP Values for fr_scomp and fr_dcomp (source and destination port value comparisons) : .LP .nf FR_NONE 0 FR_EQUAL 1 FR_NEQUAL 2 FR_LESST 3 FR_GREATERT 4 FR_LESSTE 5 FR_GREATERTE 6 FR_OUTRANGE 7 FR_INRANGE 8 .fi .PP The third ioctl, SIOCIPFFL, flushes either the input filter list, the output filter list or both and it returns the number of filters removed from the list(s). The values which it will take and recognise are FR_INQUE and FR_OUTQUE (see above). This ioctl is also implemented for \fB/dev/ipstate\fP and will flush all state tables entries if passed 0 or just all those which are not established if passed 1. .IP "\fBGeneral Logging Flags\fP" 0 There are two flags which can be set to log packets independently of the rules used. These allow for packets which are either passed or blocked to be logged. To set (and clear)/get these flags, two ioctls are provided: .IP SIOCSETFF 16 Takes an unsigned integer as the parameter. The flags are then set to those provided (clearing/setting all in one). .nf FF_LOGPASS 0x10000000 FF_LOGBLOCK 0x20000000 FF_LOGNOMATCH 0x40000000 FF_BLOCKNONIP 0x80000000 /* Solaris 2.x only */ .fi .IP SIOCGETFF 16 Takes a pointer to an unsigned integer as the parameter. A copy of the flags currently in used is copied to user space. .IP "\fBFilter statistics\fP" 0 Statistics on the various operations performed by this package on packets is kept inside the kernel. These statistics apply to packets traversing through the kernel. To retrieve this structure, use this ioctl: .nf ioctl(fd, SIOCGETFS, struct friostat *) struct friostat { struct filterstats f_st[2]; struct frentry *f_fin[2]; struct frentry *f_fout[2]; struct frentry *f_acctin[2]; struct frentry *f_acctout[2]; struct frentry *f_auth; u_long f_froute[2]; int f_active; /* 1 or 0 - active rule set */ int f_defpass; /* default pass - from fr_pass */ int f_running; /* 1 if running, else 0 */ int f_logging; /* 1 if enabled, else 0 */ char f_version[32]; /* version string */ }; struct filterstats { u_long fr_pass; /* packets allowed */ u_long fr_block; /* packets denied */ u_long fr_nom; /* packets which don't match any rule */ u_long fr_ppkl; /* packets allowed and logged */ u_long fr_bpkl; /* packets denied and logged */ u_long fr_npkl; /* packets unmatched and logged */ u_long fr_pkl; /* packets logged */ u_long fr_skip; /* packets to be logged but buffer full */ - u_long fr_ret; /* packets for which a return is sent */ +( u_long fr_ret; /* packets for which a return is sent */); u_long fr_acct; /* packets for which counting was performed */ u_long fr_bnfr; /* bad attempts to allocate fragment state */ u_long fr_nfr; /* new fragment state kept */ u_long fr_cfr; /* add new fragment state but complete pkt */ u_long fr_bads; /* bad attempts to allocate packet state */ u_long fr_ads; /* new packet state kept */ u_long fr_chit; /* cached hit */ u_long fr_pull[2]; /* good and bad pullup attempts */ #if SOLARIS u_long fr_notdata; /* PROTO/PCPROTO that have no data */ u_long fr_nodata; /* mblks that have no data */ u_long fr_bad; /* bad IP packets to the filter */ u_long fr_notip; /* packets passed through no on ip queue */ u_long fr_drop; /* packets dropped - no info for them! */ #endif }; .fi If we wanted to retrieve all the statistics and reset the counters back to 0, then the ioctl() call would be made to SIOCFRZST rather than SIOCGETFS. In addition to the statistics above, each rule keeps a hit count, counting both number of packets and bytes. To reset these counters for a rule, load the various rule information into a frentry structure and call SIOCZRLST. .IP "Swapping Active lists" 0 IP Filter supports two lists of rules for filtering and accounting: an active list and an inactive list. This allows for large scale rule base changes to be put in place atomically with otherwise minimal interruption. Which of the two is active can be changed using the SIOCSWAPA ioctl. It is important to note that no passed argument is recognised and that the value returned is that of the list which is now inactive. .br .SH FILES /dev/ipauth .br /dev/ipl .br /dev/ipnat .br /dev/ipstate .SH SEE ALSO ipl(4), ipnat(4), ipf(5), ipf(8), ipfstat(8) diff --git a/sbin/ipf/ipf/ipf.5 b/sbin/ipf/ipf/ipf.5 index 8ef56493df5a..2b5d756531eb 100644 --- a/sbin/ipf/ipf/ipf.5 +++ b/sbin/ipf/ipf/ipf.5 @@ -1,1698 +1,1698 @@ .\" $FreeBSD$ .TH IPF 5 .SH NAME ipf, ipf.conf \- IPFilter firewall rules file format .SH DESCRIPTION .PP The ipf.conf file is used to specify rules for the firewall, packet authentication and packet accounting components of IPFilter. To load rules specified in the ipf.conf file, the ipf(8) program is used. .PP For use as a firewall, there are two important rule types: those that block and drop packets (block rules) and those that allow packets through (pass rules.) Accompanying the decision to apply is a collection of statements that specify under what conditions the result is to be applied and how. .PP The simplest rules that can be used in ipf.conf are expressed like this: .PP .nf block in all pass out all .fi .PP Each rule must contain at least the following three components .RS .IP * a decision keyword (pass, block, etc.) .IP * the direction of the packet (in or out) .IP * address patterns or "all" to match any address information .RE .SS Long lines .PP For rules lines that are particularly long, it is possible to split them over multiple lines implicity like this: .PP .nf pass in on bgeo proto tcp from 1.1.1.1 port > 1000 to 2.2.2.2 port < 5000 flags S keep state .fi .PP or explicitly using the backslash ('\\') character: .PP .nf pass in on bgeo proto tcp from 1.1.1.1 port > 1000 \\ to 2.2.2.2 port < 5000 flags S keep state .fi .SS Comments .PP Comments in the ipf.conf file are indicated by the use of the '#' character. This can either be at the start of the line, like this: .PP .nf # Allow all ICMP packets in pass in proto icmp from any to any .fi .PP Or at the end of a like, like this: .PP .nf pass in proto icmp from any to any # Allow all ICMP packets in .fi .SH Firewall rules .PP This section goes into detail on how to construct firewall rules that are placed in the ipf.conf file. .PP It is beyond the scope of this document to describe what makes a good firewall rule set or which packets should be blocked or allowed in. Some suggestions will be provided but further reading is expected to fully understand what is safe and unsafe to allow in/out. .SS Filter rule keywords .PP The first word found in any filter rule describes what the eventual outcome of a packet that matches it will be. Descriptions of the many and various sections that can be used to match on the contents of packet headers will follow on below. .PP The complete list of keywords, along with what they do is as follows: .RS .HP pass rules that match a packet indicate to ipfilter that it should be allowed to continue on in the direction it is flowing. .HP block rules are used when it is desirable to prevent a packet from going any further. Packets that are blocked on the "in" side are never seen by TCP/IP and those that are blocked going "out" are never seen on the wire. .HP log when IPFilter successfully matches a packet against a log rule a log record is generated and made available for ipmon(8) to read. These rules have no impact on whether or not a packet is allowed through or not. So if a packet first matched a block rule and then matched a log rule, the status of the packet after the log rule is that it will still be blocked. .HP count rules provide the administrator with the ability to count packets and bytes that match the criteria laid out in the configuration file. The count rules are applied after NAT and filter rules on the inbound path. For outbound packets, count rules are applied before NAT and before the packet is dropped. Thus the count rule cannot be used as a true indicator of link layer .HP auth rules cause the matching packet to be queued up for processing by a user space program. The user space program is responsible for making an ioctl system call to collect the information about the queued -packet and another ioctl system call to return the verdict (block, +packet( and another ioctl system call to return the verdict (block,); pass, etc) on what to do with the packet. In the event that the queue becomes full, the packets will end up being dropped. .HP call provides access to functions built into IPFilter that allow for more complex actions to be taken as part of the decision making that goes with the rule. .HP decapsulate rules instruct ipfilter to remove any other headers (IP, UDP, AH) and then process what is inside as a new packet. For non-UDP packets, there are builtin checks that are applied in addition to whatever is specified in the rule, to only allow decapsulation of recognised protocols. After decapsulating the inner packet, any filtering result that is applied to the inner packet is also applied to the other packet. .PP The default way in which filter rules are applied is for the last matching rule to be used as the decision maker. So even if the first rule to match a packet is a pass, if there is a later matching rule that is a block and no further rules match the packet, then it will be blocked. .SS Matching Network Interfaces .PP On systems with more than one network interface, it is necessary to be able to specify different filter rules for each of them. In the first instance, this is because different networks will send us packets via each network interface but it is also because of the hosts, the role and the resulting security policy that we need to be able to distinguish which network interface a packet is on. .PP To accomodate systems where the presence of a network interface is dynamic, it is not necessary for the network interface named in a filter rule to be present in the system when the rule is loaded. This can lead to silent errors being introduced and unexpected behaviour with the simplest of keyboard mistakes - for example, typing in hem0 instead of hme0 or hme2 instead of hme3. .PP On Solaris systems prior to Solaris 10 Update 4, it is not possible to filter packets on the loopback interface (lo0) so filter rules that specify it will have no impact on the corresponding flow of packets. See below for Solaris specific tips on how to enable this. .PP Some examples of including the network interface in filter rules are: .PP .nf block in on bge0 all pass out on bge0 all .fi .SS Address matching (basic) .PP The first and most basic part of matching for filtering rules is to specify IP addresses and TCP/UDP port numbers. The source address information is matched by the "from" information in a filter rule and the destination address information is matched with the "to" information in a filter rule. .PP The typical format used for IP addresses is CIDR notation, where an IP address (or network) is followed by a '/' and a number representing the size of the netmask in bits. This notation is used for specifying address matching in both IPv4 and IPv6. If the '/' and bitmask size are excluded from the matching string, it is assumed that the address specified is a host address and that the netmask applied should be all 1's. .PP Some examples of this are: .PP .nf pass in from 10.1.0.0/24 to any block out from any to 10.1.1.1 .fi .PP It is not possible to specify a range of addresses that does not have a boundary that can be defined by a standard subnet mask. .IP .B Names instead of addresses .RS .PP Hostnames, resolved either via DNS or /etc/hosts, or network names, resolved via /etc/networks, may be used in place of actual addresses in the filter rules. WARNING: if a hostname expands to more than one address, only the *first* is used in building the filter rule. .PP Caution should be exercised when relying on DNS for filter rules in case the sending and receiving of DNS packets is blocked when ipf(8) is processing that part of the configuration file, leading to long delays, if not errors, in loading the filter rules. .RE .SS Protocol Matching .PP To match packets based on TCP/UDP port information, it is first necessary to indicate which protocol the packet must be. This is done using the "proto" keyword, followed by either the protocol number or a name which is mapped to the protocol number, usually through the /etc/protocols file. .PP .nf pass in proto tcp from 10.1.0.0/24 to any block out proto udp from any to 10.1.1.1 pass in proto icmp from any to 192.168.0.0/16 .fi .SS Sending back error packets .PP When a packet is just discarded using a block rule, there is no feedback given to the host that sent the packet. This is both good and bad. If this is the desired behaviour and it is not desirable to send any feedback about packets that are to be denied. The catch is that often a host trying to connect to a TCP port or with a UDP based application will send more than one packet because it assumes that just one packet may be discarded so a retry is required. The end result being logs can become cluttered with duplicate entries due to the retries. .PP To address this problem, a block rule can be qualified in two ways. The first of these is specific to TCP and instructs IPFilter to send back a reset (RST) packet. This packet indicates to the remote system that the packet it sent has been rejected and that it shouldn't make any further -attempts to send packets to that port. Telling IPFilter to return a TCP +attempts( to send packets to that port. Telling IPFilter to return a TCP); RST packet in response to something that has been received is achieved with the return-rst keyword like this: .PP .nf block return-rst in proto tcp from 10.0.0.0/8 to any .fi .PP When sending back a TCP RST packet, IPFilter must construct a new packet that has the source address of the intended target, not the source address of the system it is running on (if they are different.) .PP For all of the other protocols handled by the IP protocol suite, to send back an error indicating that the received packet was dropped requires sending back an ICMP error packet. Whilst these can also be used for TCP, the sending host may not treat the received ICMP error as a hard error -in the same way as it does the TCP RST packet. To return an ICMP error +in( the same way as it does the TCP RST packet. To return an ICMP error); it is necessary to place return-icmp after the block keyword like this: .PP .nf block return-icmp in proto udp from any to 192.168.0.1/24 .fi .PP -When electing to return an ICMP error packet, it is also possible to +When( electing to return an ICMP error packet, it is also possible to); select what type of ICMP error is returned. Whilst the full compliment of ICMP unreachable codes can be used by specifying a number instead of the string below, only the following should be used in conjunction with -return-icmp. Which return code to use is a choice to be made when +return-icmp.( Which return code to use is a choice to be made when); weighing up the pro's and con's. Using some of the codes may make it more obvious that a firewall is being used rather than just the host not responding. .RS .HP filter-prohib (prohibited by filter) sending packets to the destination given in the received packet is prohibited due to the application of a packet filter .HP net-prohib (prohibited network) sending packets to the destination given in the received packet is administratively prohibited. .HP host-unk (host unknown) the destination host address is not known by the system receiving the packet and therefore cannot be reached. .HP host-unr (host unreachable) it is not possible to reach the host as given by the destination address in the packet header. .HP net-unk (network unknown) the destination network address is not known by the system receiving the packet and therefore cannot be reached. .HP net-unr (network unreachable) it is not possible to forward the packet on to its final destination as given by the destination address .HP port-unr (port unreachable) there is no application using the given destination port and therefore it is not possible to reach that port. .HP proto-unr (protocol unreachable) the IP protocol specified in the packet is not available to receive packets. .DE .PP An example that shows how to send back a port unreachable packet for UDP packets to 192.168.1.0/24 is as follows: .PP .nf block return-icmp(port-unr) in proto udp from any to 192.168.1.0/24 .fi .PP In the above examples, when sending the ICMP packet, IPFilter will construct a new ICMP packet with a source address of the network interface used to send the packet back to the original source. This can give away that there is an intermediate system blocking packets. To have IPFilter send back ICMP packets where the source address is the original destination, regardless of whether or not it is on the local host, return-icmp-as-dest is used like this: .PP .nf block return-icmp-as-dest(port-unr) in proto udp \\ from any to 192.168.1.0/24 .fi .SS TCP/UDP Port Matching .PP Having specified which protocol is being matched, it is then possible to indicate which port numbers a packet must have in order to match the rule. Due to port numbers being used differently to addresses, it is therefore possible to match on them in different ways. IPFilter allows you to use the following logical operations: .IP "< x" is true if the port number is greater than or equal to x and less than or equal to y is true if the port number in the packet is less than x .IP "<= x" is true if the port number in the packet is less than or equal to x .IP "> x" is true if the port number in the packet is greater than x .IP ">= x" is true if the port number in the packet is greater or equal to x .IP "= x" is true if the port number in the packet is equal to x .IP "!= x" is true if the port number in the packet is not equal to x .PP Additionally, there are a number of ways to specify a range of ports: .IP "x <> y" is true if the port number is less than a and greater than y .IP "x >< y" is true if the port number is greater than x and less than y .IP "x:y" is true if the port number is greater than or equal to x and less than or equal to y .PP Some examples of this are: .PP .nf block in proto tcp from any port >= 1024 to any port < 1024 pass in proto tcp from 10.1.0.0/24 to any port = 22 block out proto udp from any to 10.1.1.1 port = 135 pass in proto udp from 1.1.1.1 port = 123 to 10.1.1.1 port = 123 pass in proto tcp from 127.0.0.0/8 to any port 6000:6009 .fi .PP If there is no desire to mention any specific source or destintion information in a filter rule then the word "all" can be used to indicate that all addresses are considered to match the rule. .SS IPv4 or IPv6 .PP If a filter rule is constructed without any addresses then IPFilter will attempt to match both IPv4 and IPv6 packets with it. In the next list of rules, each one can be applied to either network protocol because there is no address specified from which IPFilter can derive with network protocol to expect. .PP .nf pass in proto udp from any to any port = 53 block in proto tcp from any port < 1024 to any .fi .PP To explicitly match a particular network address family with a specific rule, the family must be added to the rule. For IPv4 it is necessary to add family inet and for IPv6, family inet6. Thus the next rule will block all packets (both IPv4 and IPv6: .PP .nf block in all .fi .PP but in the following example, we block all IPv4 packets and only allow in IPv6 packets: .PP .nf block in family inet all pass in family inet6 all .fi .PP To continue on from the example where we allowed either IPv4 or IPv6 packets to port 53 in, to change that such that only IPv6 packets to port 53 need to allowed blocked then it is possible to add in a protocol family qualifier: .PP .nf pass in family inet6 proto udp from any to any port = 53 .fi .SS First match vs last match .PP To change the default behaviour from being the last matched rule decides the outcome to being the first matched rule, the word "quick" is inserted to the rule. .SH Extended Packet Matching .SS Beyond using plain addresses .PP On firewalls that are working with large numbers of hosts and networks or simply trying to filter discretely against various hosts, it can be an easier administration task to define a pool of addresses and have a filter rule reference that address pool rather than have a rule for each address. .PP In addition to being able to use address pools, it is possible to use the interface name(s) in the from/to address fields of a rule. If the name being used in the address section can be matched to any of the interface names mentioned in the rule's "on" or "via" fields then it can be used with one of the following keywords for extended effect: .HP broadcast use the primary broadcast address of the network interface for matching packets with this filter rule; .IP .nf pass in on fxp0 proto udp from any to fxp0/broadcast port = 123 .fi .HP peer use the peer address on point to point network interfaces for matching packets with this filter rule. This option typically only has meaningful use with link protocols such as SLIP and PPP. For example, this rule allows ICMP packets from the remote peer of ppp0 to be received if they're destined for the address assigned to the link at the firewall end. .IP .nf pass in on ppp0 proto icmp from ppp0/peer to ppp0/32 .fi .HP netmasked use the primary network address, with its netmask, of the network interface for matching packets with this filter rule. If a network interface had an IP address of 192.168.1.1 and its netmask was 255.255.255.0 (/24), then using the word "netmasked" after the interface name would match any addresses that would match 192.168.1.0/24. If we assume that bge0 has this IP address and netmask then the following two rules both serve to produce the same effect: .IP .nf pass in on bge0 proto icmp from any to 192.168.1.0/24 pass in on bge0 proto icmp from any to bge0/netmasked .fi .HP network using the primary network address, and its netmask, of the network interface, construct an address for exact matching. If a network interface has an address of 192.168.1.1 and its netmask is 255.255.255.0, using this option would only match packets to 192.168.1.0. .IP .nf pass in on bge0 proto icmp from any to bge0/network .fi .PP Another way to use the name of a network interface to get the address is to wrap the name in ()'s. In the above method, IPFilter looks at the interface names in use and to decide whether or not the name given is a hostname or network interface name. With the use of ()'s, it is possible to tell IPFilter that the name should be treated as a network interface name even though it doesn't appear in the list of network interface that the rule ias associated with. .IP .nf pass in proto icmp from any to (bge0)/32 .fi .SS Using address pools .PP Rather than list out multiple rules that either allow or deny specific addresses, it is possible to create a single object, call an address pool, that contains all of those addresses and reference that in the filter rule. For documentation on how to write the configuration file for those pools and load them, see ippool.conf(5) and ippool(8). There are two types of address pools that can be defined in ippool.conf(5): trees and hash tables. To refer to a tree defined in ippool.conf(5), use this syntax: .PP .nf pass in from pool/trusted to any .fi .PP Either a name or number can be used after the '/', just so long as it matches up with something that has already been defined in ipool.conf(5) and loaded in with ippool(8). Loading a filter rule that references a pool that does not exist will result in an error. .PP If hash tables have been used in ippool.conf(5) to store the addresses in instead of a tree, then replace the word pool with hash: .IP .nf pass in from any to hash/webservers .fi .PP There are different operational characteristics with each, so there may be some situations where a pool works better than hash and vice versa. .SS Matching TCP flags .PP The TCP header contains a field of flags that is used to decide if the packet is a connection request, connection termination, data, etc. By matching on the flags in conjunction with port numbers, it is possible to restrict the way in which IPFilter allows connections to be created. A quick overview of the TCP flags is below. Each is listed with the letter used in IPFilter rules, followed by its three or four letter pneumonic. .HP S SYN - this bit is set when a host is setting up a connection. The initiator typically sends a packet with the SYN bit and the responder sends back SYN plus ACK. .HP A ACK - this bit is set when the sender wishes to acknowledge the receipt of a packet from another host .HP P PUSH - this bit is set when a sending host has send some data that is yet to be acknowledged and a reply is sought .HP F FIN - this bit is set when one end of a connection starts to close the connection down .HP U URG - this bit is set to indicate that the packet contains urgent data .HP R RST - this bit is set only in packets that are a reply to another that has been received but is not targetted at any open port .HP C CWN .HP E ECN .PP When matching TCP flags, it is normal to just list the flag that you wish to be set. By default the set of flags it is compared against is "FSRPAU". Rules that say "flags S" will be displayed by ipfstat(8) as having "flags S/FSRPAU". This is normal. The last two flags, "C" and "E", are optional - they may or may not be used by an end host and have no bearing on either the acceptance of data nor control of the connection. Masking them out with "flags S/FSRPAUCE" may cause problems for remote hosts making a successful connection. .PP .nf pass in quick proto tcp from any to any port = 22 flags S/SAFR pass out quick proto tcp from any port = 22 to any flags SA .fi .PP By itself, filtering based on the TCP flags becomes more work but when combined with stateful filtering (see below), the situation changes. .SS Matching on ICMP header information .PP The TCP and UDP are not the only protocols for which filtering beyond just the IP header is possible, extended matching on ICMP packets is also available. The list of valid ICMP types is different for IPv4 vs IPv6. .PP As a practical example, to allow the ping command to work against a specific target requires allowing two different types of ICMP packets, like this: .PP .nf pass in proto icmp from any to webserver icmp-type echo pass out proto icmp from webserver to any icmp-type echorep .fi .PP The ICMP header has two fields that are of interest for filtering: the ICMP type and code. Filter rules can accept either a name or number for both the type and code. The list of names supported for ICMP types is listed below, however only ICMP unreachable errors have named codes (see above.) .PP The list of ICMP types that are available for matching an IPv4 packet are as follows: .PP echo (echo request), echorep (echo reply), inforeq (information request), inforep (information reply), maskreq (mask request), maskrep (mask reply), paramprob (parameter problem), redir (redirect), routerad (router advertisement), routersol (router solicit), squence (source quence), timest (timestamp), timestreq (timestamp reply), timex (time exceeded), unreach (unreachable). .PP The list of ICMP types that are available for matching an IPv6 packet are as follows: .PP echo (echo request), echorep (echo reply), fqdnquery (FQDN query), fqdnreply (FQDN reply), inforeq (information request), inforep (information reply), listendone (MLD listener done), listendqry (MLD listener query), listendrep (MLD listener reply), neighadvert (neighbour advert), neighborsol (neighbour solicit), paramprob (parameter problem), redir (redirect), renumber (router renumbering), routerad (router advertisement), routersol (router solicit), timex (time exceeded), toobig (packet too big), unreach (unreachable, whoreq (WRU request), whorep (WRU reply). .SH Stateful Packet Filtering .PP Stateful packet filtering is where IPFilter remembers some information from one or more packets that it has seen and is able to apply it to future packets that it receives from the network. .PP What this means for each transport layer protocol is different. For TCP it means that if IPFilter sees the very first packet of an attempt to make a connection, it has enough information to allow all other subsequent packets without there needing to be any explicit rules to match them. IPFilter uses the TCP port numbers, TCP flags, window size and sequence numbers to determine which packets should be matched. For UDP, only the UDP port numbers are available. For ICMP, the ICMP types can be combined with the ICMP id field to determine which reply packets match a request/query that has already been seen. For all other protocols, only matching on IP address and protocol number is available for determining if a packet received is a mate to one that has already been let through. .PP The difference this makes is a reduction in the number of rules from 2 or 4 to 1. For example, these 4 rules: .PP .nf pass in on bge0 proto tcp from any to any port = 22 pass out on bge1 proto tcp from any to any port = 22 pass in on bge1 proto tcp from any port = 22 to any pass out on bge0 proto tcp from any port = 22 to any .fi .PP can be replaced with this single rule: .PP .nf pass in on bge0 proto tcp from any to any port = 22 flags S keep state .fi .PP Similar rules for UDP and ICMP might be: .PP .nf pass in on bge0 proto udp from any to any port = 53 keep state pass in on bge0 proto icmp all icmp-type echo keep state .fi .PP When using stateful filtering with TCP it is best to add "flags S" to the rule to ensure that state is only created when a packet is seen that is an indication of a new connection. Although IPFilter can gather some information from packets in the middle of a TCP connection to do stateful filtering, there are some options that are only sent at the start of the connection which alter the valid window of what TCP accepts. The end result of trying to pickup TCP state in mid connection is that some later packets that are part of the connection may not match the known state information and be dropped or blocked, causing problems. If a TCP packet matches IP addresses and port numbers but does not fit into the recognised window, it will not be automatically allowed and will be flagged inside of IPFitler as "out of window" (oow). See below, "Extra packet attributes", for how to match on this attribute. .PP Once a TCP connection has reached the established state, the default timeout allows for it to be idle for 5 days before it is removed from the state table. The timeouts for the other TCP connection states vary from 240 seconds to 30 seconds. Both UDP and ICMP state entries have asymetric timeouts where the timeout set upon seeing packets in the forward direction is much larger than for the reverse direction. For UDP the default timeouts are 120 and 12 seconds, for ICMP 60 and 6 seconds. This is a reflection of the use of these protocols being more for query-response than for ongoing connections. For all other protocols the timeout is 60 seconds in both directions. .SS Stateful filtering options .PP The following options can be used with stateful filtering: .HP limit limit the number of state table entries that this rule can create to the number given after limit. A rule that has a limit specified is always permitted that many state table entries, even if creating an additional entry would cause the table to have more entries than the otherwise global limit. .IP .nf pass ... keep state(limit 100) .fi .HP age sets the timeout for the state entry when it sees packets going through it. Additionally it is possible to set the tieout for the reply packets that come back through the firewall to a different value than for the forward path. allowing a short timeout to be set after the reply has been seen and the state no longer required. .RS .PP .nf pass in quick proto icmp all icmp-type echo \\ keep state (age 3) pass in quick proto udp from any \\ to any port = 53 keep state (age 30/1) .fi .RE .HP strict only has an impact when used with TCP. It forces all packets that are allowed through the firewall to be sequential: no out of order delivery of packets is allowed. This can cause significant slowdown for some connections and may stall others. Use with caution. .IP .nf pass in proto tcp ... keep state(strict) .fi .HP noicmperr prevents ICMP error packets from being able to match state table entries created with this flag using the contents of the original packet included. .IP .nf pass ... keep state(noicmperr) .fi .HP sync indicates to IPFilter that it needs to provide information to the user land daemons responsible for syncing other machines state tables up with this one. .IP .nf pass ... keep state(sync) .fi .HP nolog do not generate any log records for the creation or deletion of state table entries. .IP .nf pass ... keep state(nolog) .fi .HP icmp-head rather than just precent ICMP error packets from being able to match state table entries, allow an ACL to be processed that can filter in or out ICMP error packets based as you would with normal firewall rules. The icmp-head option requires a filter rule group number or name to be present, just as you would use with head. .RS .PP .nf pass in quick proto tcp ... keep state(icmp-head 101) block in proto icmp from 10.0.0.0/8 to any group 101 .fi .RE .HP max-srcs allows the number of distinct hosts that can create a state entry to be defined. .IP .nf pass ... keep state(max-srcs 100) pass ... keep state(limit 1000, max-srcs 100) .fi .HP max-per-src whilst max-srcs limits the number of individual hosts that may cause the creation of a state table entry, each one of those hosts is still table to fill up the state table with new entries until the global maximum is reached. This option allows the number of state table entries per address to be limited. .IP .nf pass ... keep state(max-srcs 100, max-per-src 1) pass ... keep state(limit 100, max-srcs 100, max-per-src 1) .fi .IP Whilst these two rules might seem identical, in that they both ultimately limit the number of hosts and state table entries created from the rule to 100, there is a subtle difference: the second will always allow up to 100 state table entries to be created whereas the first may not if the state table fills up from other rules. .IP Further, it is possible to specify a netmask size after the per-host limit that enables the per-host limit to become a per-subnet or per-network limit. .IP .nf pass ... keep state(max-srcs 100, max-per-src 1/24) .fi .IP If there is no IP protocol implied by addresses or other features of the rule, IPFilter will assume that no netmask is an all ones netmask for both IPv4 and IPv6. .SS Tieing down a connection .PP For any connection that transits a firewall, each packet will be seen twice: once going in and once going out. Thus a connection has 4 flows of packets: .HP forward inbound packets .HP forward outbound packets .HP reverse inbound packets .HP reverse outbound packets .PP IPFilter allows you to define the network interface to be used at all four points in the flow of packets. For rules that match inbound packets, out-via is used to specify which interfaces the packets go out, For rules that match outbound packets, in-via is used to match the inbound packets. In each case, the syntax generalises to this: .PP .nf pass ... in on forward-in,reverse-in \\ out-via forward-out,reverse-out ... pass ... out on forward-out,reverse-out \\ in-via forward-in,reverse-in ... .fi .PP An example that pins down all 4 network interfaces used by an ssh connection might look something like this: .PP .nf pass in on bge0,bge1 out-via bge1,bge0 proto tcp \\ from any to any port = 22 flags S keep state .fi .SS Working with packet fragments .PP Fragmented packets result in 1 packet containing all of the layer 3 and 4 header information whilst the data is split across a number of other packets. .PP To enforce access control on fragmented packets, one of two approaches can be taken. The first is to allow through all of the data fragments (those that made up the body of the original packet) and rely on matching the header information in the "first" fragment, when it is seen. The reception of body fragments without the first will result in the receiving host being unable to completely reassemble the packet and discarding all of the fragments. The following three rules deny all fragmented packets from being received except those that are UDP and even then only allows those destined for port 2049 to be completed. .PP .nf block in all with frags pass in proto udp from any to any with frag-body pass in proto udp from any to any port = 2049 with frags .fi .PP Another mechanism that is available is to track "fragment state". This relies on the first fragment of a packet that arrives to be the fragment that contains all of the layer 3 and layer 4 header information. With the receipt of that fragment before any other, it is possible to determine which other fragments are to be allowed through without needing to explicitly allow all fragment body packets. An example of how this is done is as follows: .PP .nf pass in proto udp from any port = 2049 to any with frags keep frags .fi .SH Building a tree of rules .PP Writing your filter rules as one long list of rules can be both inefficient in terms of processing the rules and difficult to understand. To make the construction of filter rules easier, it is possible to place them in groups. A rule can be both a member of a group and the head of a new group. .PP Using filter groups requires at least two rules: one to be in the group one one to send matchign packets to the group. If a packet matches a filtre rule that is a group head but does not match any of the rules in that group, then the packet is considered to have matched the head rule. .PP Rules that are a member of a group contain the word group followed by either a name or number that defines which group they're in. Rules that form the branch point or starting point for the group must use the word head, followed by either a group name or number. If rules are loaded in that define a group but there is no matching head then they will effectively be orphaned rules. It is possible to have more than one head rule point to the same group, allowing groups to be used like subroutines to implement specific common policies. .PP A common use of filter groups is to define head rules that exist in the filter "main line" for each direction with the interfaces in use. For example: .PP .nf block in quick on bge0 all head 100 block out quick on bge0 all head 101 block in quick on fxp0 all head internal-in block out quick on fxp0 all head internal-out pass in quick proto icmp all icmp-type echo group 100 .fi .PP In the above set of rules, there are four groups defined but only one of them has a member rule. The only packets that would be allowed through the above ruleset would be ICMP echo packets that are received on bge0. .PP Rules can be both a member of a group and the head of a new group, allowing groups to specialise. .PP .nf block in quick on bge0 all head 100 block in quick proto tcp all head 1006 group 100 .fi .PP Another use of filter rule groups is to provide a place for rules to be dynamically added without needing to worry about their specific ordering amongst the entire ruleset. For example, if I was using this simple ruleset: .PP .nf block in quick all with bad block in proto tcp from any to any port = smtp head spammers pass in quick proto tcp from any to any port = smtp flags S keep state .fi .PP and I was getting lots of connections to my email server from 10.1.1.1 to deliver spam, I could load the following rule to complement the above: .IP .nf block in quick from 10.1.1.1 to any group spammers .fi .SS Decapsulation .PP Rule groups also form a different but vital role for decapsulation rules. With the following simple rule, if IPFilter receives an IP packet that has an AH header as its layer 4 payload, IPFilter would adjust its view of the packet internally and then jump to group 1001 using the data beyond the AH header as the new transport header. .PP .nf decapsulate in proto ah all head 1001 .fi .PP For protocols that are recognised as being used with tunnelling or otherwise encapsulating IP protocols, IPFilter is able to decide what it has on the inside without any assistance. Some tunnelling protocols use UDP as the transport mechanism. In this case, it is necessary to instruct IPFilter as to what protocol is inside UDP. .PP .nf decapsulate l5-as(ip) in proto udp from any \\ to any port = 1520 head 1001 .fi .PP Currently IPFilter only supports finding IPv4 and IPv6 headers directly after the UDP header. .PP If a packet matches a decapsulate rule but fails to match any of the rules that are within the specified group, processing of the packet continues to the next rule after the decapsulate and IPFilter's internal view of the packet is returned to what it was prior to the decapsulate rule. .PP It is possible to construct a decapsulate rule without the group head at the end that ipf(8) will accept but such rules will not result in anything happening. .SS Policy Based Routing .PP With firewalls being in the position they often are, at the boundary of different networks connecting together and multiple connections that have different properties, it is often desirable to have packets flow in a direction different to what the routing table instructs the kernel. These decisions can often be extended to changing the route based on both source and destination address or even port numbers. .PP To support this kind of configuration, IPFilter allows the next hop destination to be specified with a filter rule. The next hop is given with the interface name to use for output. The syntax for this is interface:ip.address. It is expected that the address given as the next hop is directly connected to the network to which the interface is. .PP .nf pass in on bge0 to bge1:1.1.1.1 proto tcp \\ from 1.1.2.3 to any port = 80 flags S keep state .fi .PP When this feature is combined with stateful filtering, it becomes possible to influence the network interface used to transmit packets in both directions because we now have a sense for what its reverse flow of packets is. .PP .nf pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\ proto tcp from 1.1.2.3 to any port = 80 flags S keep state .fi .PP If the actions of the routing table are perfectly acceptable, but you would like to mask the presence of the firewall by not changing the TTL in IP packets as they transit it, IPFilter can be instructed to do a "fastroute" action like this: .PP .nf pass in on bge0 fastroute proto icmp all .fi .PP This should be used with caution as it can lead to endless packet loops. Additionally, policy based routing does not change the IP header's TTL value. .PP A variation on this type of rule supports a duplicate of the original packet being created and sent out a different network. This can be useful for monitoring traffic and other purposes. .PP .nf pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\ dup-to fxp0:10.0.0.1 proto tcp from 1.1.2.3 \\ to any port = 80 flags S keep state .fi .SS Matching IPv4 options .PP The design for IPv4 allows for the header to be upto 64 bytes long, however most traffic only uses the basic header which is 20 bytes long. The other 44 bytes can be uesd to store IP options. These options are generally not necessary for proper interaction and function on the Internet today. For most people it is sufficient to block and drop all packets that have any options set. This can be achieved with this rule: .PP .nf block in quick all with ipopts .fi .PP This rule is usually placed towards the top of the configuration so that all incoming packets are blocked. .PP If you wanted to allow in a specific IP option type, the syntax changes slightly: .PP .nf pass in quick proto igmp all with opt rtralrt .fi .PP The following is a list of IP options that most people encounter and what their use/threat is. .HP lsrr (loose source route) the sender of the packet includes a list of addresses that they wish the packet to be routed through to on the way to the destination. Because replies to such packets are expected to use the list of addresses in reverse, hackers are able to very effectively use this header option in address spoofing attacks. .HP rr (record route) the sender allocates some buffer space for recording the IP address of each router that the packet goes through. This is most often used with ping, where the ping response contains a copy of all addresses from the original packet, telling the sender what route the packet took to get there. Due to performance and security issues with IP header options, this is almost no longer used. .HP rtralrt (router alert) this option is often used in IGMP messages as a flag to routers that the packet needs to be handled differently. It is unlikely to ever be received from an unknown sender. It may be found on LANs or otherwise controlled networks where the RSVP protocol and multicast traffic is in heavy use. .HP ssrr (strict source route) the sender of the packet includes a list of addresses that they wish the packet to be routed through to on the way to the destination. Where the lsrr option allows the sender to specify only some of the nodes the packet must go through, with the ssrr option, every next hop router must be specified. .PP The complete list of IPv4 options that can be matched on is: addext (Address Extention), cipso (Classical IP Security Option), dps (Dynamic Packet State), e-sec (Extended Security), eip (Extended Internet Protocol), encode (ENCODE), finn (Experimental Flow Control), imitd (IMI Traffic Descriptor), lsrr (Loose Source Route), mtup (MTU Probe - obsolete), mtur (MTU response - obsolete), nop (No Operation), nsapa (NSAP Address), rr (Record Route), rtralrt (Router Alert), satid (Stream Identifier), sdb (Selective Directed Broadcast), sec (Security), ssrr (Strict Source Route), tr (Tracerote), ts (Timestamp), ump (Upstream Multicast Packet), visa (Experimental Access Control) and zsu (Experimental Measurement). .SS Security with CIPSO and IPSO .PP IPFilter supports filtering on IPv4 packets using security attributes embedded in the IP options part of the packet. These options are usually only used on networks and systems that are using lablled security. Unless you know that you are using labelled security and your networking is also labelled, it is highly unlikely that this section will be relevant to you. .PP With the traditional IP Security Options (IPSO), packets can be tagged with a security level. The following keywords are recognised and match with the relevant RFC with respect to the bit patterns matched: confid (confidential), rserve-1 (1st reserved value), rserve-2 (2nd reserved value), rserve-3 (3rd reserved value), rserve-4 (4th reserved value), secret (secret), topsecret (top secret), unclass (unclassified). .PP .nf block in quick all with opt sec-class unclass pass in all with opt sec-class secret .fi .SS Matching IPv6 extension headers .PP Just as it is possible to filter on the various IPv4 header options, so too it is possible to filter on the IPv6 extension headers that are placed between the IPv6 header and the transport protocol header. .PP dstopts (destination options), esp (encrypted, secure, payload), frag (fragment), hopopts (hop-by-hop options), ipv6 (IPv6 header), mobility (IP mobility), none, routing. .SS Logging .PP There are two ways in which packets can be logged with IPFilter. The first is with a rule that specifically says log these types of packets and the second is a qualifier to one of the other keywords. Thus it is possible to both log and allow or deny a packet with a single rule. .PP .nf pass in log quick proto tcp from any to any port = 22 .fi .PP When using stateful filtering, the log action becomes part of the result that is remembered about a packet. Thus if the above rule was qualified with keep state, every packet in the connection would be logged. To only log the first packet from every packet flow tracked with keep state, it is necessary to indicate to IPFilter that you only wish to log the first packet. .PP .nf pass in log first quick proto tcp from any to any port = 22 \\ flags S keep state .fi .PP If it is a requirement that the logging provide an accurate representation of which connections are allowed, the log action can be qualified with the option or-block. This allows the administrator to instruct IPFilter to block the packet if the attempt to record the packet in IPFilter's kernel log records (which have an upper bound on size) failed. Unless the system shuts down or reboots, once a log record is written into the kernel buffer, it is there until ipmon(8) reads it. .PP .nf block in log proto tcp from any to any port = smtp pass in log or-block first quick proto tcp from any \\ to any port = 22 flags S keep state .fi .PP By default, IPFilter will only log the header portion of a packet received on the network. Up to 128 bytes of a packet's body can also be logged with the body keyword. ipmon(8) will display the contents of the portion of the body logged in hex. .PP .nf block in log body proto icmp all .fi .PP When logging packets from ipmon(8) to syslog, by default ipmon(8) will control what syslog facility and priority a packet will be logged with. This can be tuned on a per rule basis like this: .PP .nf block in quick log level err all with bad pass in log level local1.info proto tcp \\ from any to any port = 22 flags S keep state .fi .PP ipfstat(8) reports how many packets have been successfully logged and how many failed attempts to log a packet there were. .SS Filter rule comments .PP If there is a desire to associate a text string, be it an administrative comment or otherwise, with an IPFilter rule, this can be achieved by giving the filter rule a comment. The comment is loaded with the rule into the kernel and can be seen when the rules are listed with ipfstat. .PP .nf pass in quick proto tcp from any \\ to port = 80 comment "all web server traffic is ok" pass out quick proto tcp from any port = 80 \\ to any comment "all web server traffic is ok" .fi .SS Tags .PP To enable filtering and NAT to correctly match up packets with rules, tags can be added at with NAT (for inbound packets) and filtering (for outbound packets.) This allows a filter to be correctly mated with its NAT rule in the event that the NAT rule changed the packet in a way that would mean it is not obvious what it was. .PP For inbound packets, IPFilter can match the tag used in the filter rules with that set by NAT. For outbound rules, it is the reverse, the filter sets the tag and the NAT rule matches up with it. .PP .nf pass in ... match-tag(nat=proxy) pass out ... set-tag(nat=proxy) .fi .PP Another use of tags is to supply a number that is only used with logging. When packets match these rules, the log tag is carried over into the log file records generated by ipmon(8). With the correct use of tools such as grep, extracting log records of interest is simplified. .PP .nf block in quick log ... set-tag(log=33) .fi .SH Filter Rule Expiration .PP IPFilter allows rules to be added into the kernel that it will remove after a specific period of time by specifying rule-ttl at the end of a rule. When listing rules in the kernel using ipfstat(8), rules that are going to expire will NOT display "rule-ttl" with the timeout, rather what will be seen is a comment with how many ipfilter ticks left the rule has to live. .PP The time to live is specified in seconds. .PP .nf pass in on fxp0 proto tcp from any \\ to port = 22 flags S keep state rule-ttl 30 .fi .SH Internal packet attributes .PP In addition to being able to filter on very specific network and transport header fields, it is possible to filter on other attributes that IPFilter attaches to a packet. These attributes are placed in a rule after the keyword "with", as can be seen with frags and frag-body above. The following is a list of the other attributes available: .HP oow the packet's IP addresses and TCP ports match an existing entry in the state table but the sequence numbers indicate that it is outside of the accepted window. .IP .nf block return-rst in quick proto tcp from any to any with not oow .fi .HP bcast this is set by IPFilter when it receives notification that the link layer packet was a broadcast packet. No checking of the IP addresses is performned to determine if it is a broadcast destination or not. .IP .nf block in quick proto udp all with bcast .fi .HP mcast this is set by IPFilter when it receives notification that the link layer packet was a multicast packet. No checking of the IP addresses is performned to determine if it is a multicast destination or not. .IP .nf pass in quick proto udp from any to any port = dns with mcast .fi .HP mbcast can be used to match a packet that is either a multicast or broadcast packet at the link layer, as indicated by the operating system. .IP .nf pass in quick proto udp from any to any port = ntp with mbcast .fi .HP nat the packet positively matched a NAT table entry. .HP bad sanity checking of the packet failed. This could indicate that the layer 3/4 headers are not properly formed. .HP bad-src when reverse path verification is enabled, this flag will be set when the interface the packet is received on does not match that which would be used to send a packet out of to the source address in the received packet. .HP bad-nat an attempt to perform NAT on the packet failed. .HP not each one of the attributes matched using the "with" keyword can also be looked for to not be present. For example, to only allow in good packets, I can do this: .PP .nf block in all pass in all with not bad .fi .SH Tuning IPFilter .PP The ipf.conf file can also be used to tune the behaviour of IPFilter, allowing, for example, timeouts for the NAT/state table(s) to be set along with their sizes. The presence and names of tunables may change from one release of IPFilter to the next. The tunables that can be changed via ipf.conf is the same as those that can be seen and modified using the -T command line option to ipf(8). .PP NOTE: When parsing ipf.conf, ipf(8) will apply the settings before loading any rules. Thus if your settings are at the top, these may be applied whilst the rules not applied if there is an error further down in the configuration file. .PP To set one of the values below, the syntax is simple: "set", followed by the name of the tuneable to set and then the value to set it to. .PP .nf set state_max 9999; set state_size 10101; .fi .PP A list of the currently available variables inside IPFilter that may be tuned from ipf.conf are as follows: .HP active set through -s command line switch of ipf(8). See ipf(8) for detals. .HP chksrc when set, enables reverse path verification on source addresses and for filters to match packets with bad-src attribute. .HP control_forwarding when set turns off kernel forwarding when IPFilter is disabled or unloaded. .HP default_pass the default policy - whether packets are blocked or passed, etc - is represented by the value of this variable. It is a bit field and the bits that can be set are found in . It is not recommended to tune this value directly. .HP ftp_debug set the debugging level of the in-kernel FTP proxy. Debug messages will be printed to the system console. .HP ftp_forcepasv when set the FTP proxy must see a PASV/EPSV command before creating the state/NAT entries for the 227 response. .HP ftp_insecure when set the FTP proxy will not wait for a user to login before allowing data connections to be created. .HP ftp_pasvonly when set the proxy will not create state/NAT entries for when it sees either the PORT or EPRT command. .HP ftp_pasvrdr when enabled causes the FTP proxy to create very insecure NAT/state entries that will allow any connection between the client and server hosts when a 227 reply is seen. Use with extreme caution. .HP ftp_single_xfer when set the FTP proxy will only allow one data connection at a time. .HP hostmap_size sets the size of the hostmap table used by NAT to store address mappings for use with sticky rules. .HP icmp_ack_timeout default timeout used for ICMP NAT/state when a reply packet is seen for an ICMP state that already exists .HP icmp_minfragmtu sets the minimum MTU that is considered acceptable in an ICMP error before deciding it is a bad packet. .HP icmp_timeout default timeout used for ICMP NAT/state when the packet matches the rule .HP ip_timeout default timeout used for NAT/state entries that are not TCP/UDP/ICMP. .HP ipf_flags .HP ips_proxy_debug this sets the debugging level for the proxy support code. When enabled, debugging messages will be printed to the system console. .HP log_all when set it changes the behaviour of "log body" to log the entire packet rather than just the first 128 bytes. .HP log_size sets the size of the in-kernel log buffer in bytes. .HP log_suppress when set, IPFilter will check to see if the packet it is logging is similar to the one it previously logged and if so, increases the occurance count for that packet. The previously logged packet must not have yet been read by ipmon(8). .HP min_ttl is used to set the TTL value that packets below will be marked with the low-ttl attribute. .HP nat_doflush if set it will cause the NAT code to do a more aggressive flush of the NAT table at the next opportunity. Once the flush has been done, the value is reset to 0. .HP nat_lock this should only be changed using ipfs(8) .HP nat_logging when set, NAT will create log records that can be read from /dev/ipnat. .HP nat_maxbucket maximum number of entries allowed to exist in each NAT hash bucket. This prevents an attacker trying to load up the hash table with entries in a single bucket, reducing performance. .HP nat_rules_size size of the hash table to store map rules. .HP nat_table_max maximum number of entries allowed into the NAT table .HP nat_table_size size of the hash table used for NAT .HP nat_table_wm_high when the fill percentage of the NAT table exceeds this mark, more aggressive flushing is enabled. .HP nat_table_wm_low this sets the percentage at which the NAT table's agressive flushing will turn itself off at. .HP rdr_rules_size size of the hash table to store rdr rules. .HP state_lock this should only be changed using ipfs(8) .HP state_logging when set, the stateful filtering will create log records that can be read from /dev/ipstate. .HP state_max maximum number of entries allowed into the state table .HP state_maxbucket maximum number of entries allowed to exist in each state hash bucket. This prevents an attacker trying to load up the hash table with entries in a single bucket, reducing performance. .HP state_size size of the hash table used for stateful filtering .HP state_wm_freq this controls how often the agressive flushing should be run once the state table exceeds state_wm_high in percentage full. .HP state_wm_high when the fill percentage of the state table exceeds this mark, more aggressive flushing is enabled. .HP state_wm_low this sets the percentage at which the state table's agressive flushing will turn itself off at. .HP tcp_close_wait timeout used when a TCP state entry reaches the FIN_WAIT_2 state. .HP tcp_closed timeout used when a TCP state entry is ready to be removed after either a RST packet is seen. .HP tcp_half_closed timeout used when a TCP state entry reaches the CLOSE_WAIT state. .HP tcp_idle_timeout timeout used when a TCP state entry reaches the ESTABLISHED state. .HP tcp_last_ack timeout used when a TCP NAT/state entry reaches the LAST_ACK state. .HP tcp_syn_received timeout applied to a TCP NAT/state entry after SYN-ACK packet has been seen. .HP tcp_syn_sent timeout applied to a TCP NAT/state entry after SYN packet has been seen. .HP tcp_time_wait timeout used when a TCP NAT/state entry reaches the TIME_WAIT state. .HP tcp_timeout timeout used when a TCP NAT/state entry reaches either the half established state (one ack is seen after a SYN-ACK) or one side is in FIN_WAIT_1. .HP udp_ack_timeout default timeout used for UDP NAT/state when a reply packet is seen for a UDP state that already exists .HP udp_timeout default timeout used for UDP NAT/state when the packet matches the rule .HP update_ipid when set, turns on changing the IP id field in NAT'd packets to a random number. .SS Table of visible variables .PP A list of all of the tunables, their minimum, maximum and current values is as follows. .PP .nf Name Min Max Current active 0 0 0 chksrc 0 1 0 control_forwarding 0 1 0 default_pass 0 MAXUINT 134217730 ftp_debug 0 10 0 ftp_forcepasv 0 1 1 ftp_insecure 0 1 0 ftp_pasvonly 0 1 0 ftp_pasvrdr 0 1 0 ftp_single_xfer 0 1 0 hostmap_size 1 MAXINT 2047 icmp_ack_timeout 1 MAXINT 12 icmp_minfragmtu 0 1 68 icmp_timeout 1 MAXINT 120 ip_timeout 1 MAXINT 120 ipf_flags 0 MAXUINT 0 ips_proxy_debug 0 10 0 log_all 0 1 0 log_size 0 524288 32768 log_suppress 0 1 1 min_ttl 0 1 4 nat_doflush 0 1 0 nat_lock 0 1 0 nat_logging 0 1 1 nat_maxbucket 1 MAXINT 22 nat_rules_size 1 MAXINT 127 nat_table_max 1 MAXINT 30000 nat_table_size 1 MAXINT 2047 nat_table_wm_high 2 100 99 nat_table_wm_low 1 99 90 rdr_rules_size 1 MAXINT 127 state_lock 0 1 0 state_logging 0 1 1 state_max 1 MAXINT 4013 state_maxbucket 1 MAXINT 26 state_size 1 MAXINT 5737 state_wm_freq 2 999999 20 state_wm_high 2 100 99 state_wm_low 1 99 90 tcp_close_wait 1 MAXINT 480 tcp_closed 1 MAXINT 60 tcp_half_closed 1 MAXINT 14400 tcp_idle_timeout 1 MAXINT 864000 tcp_last_ack 1 MAXINT 60 tcp_syn_received 1 MAXINT 480 tcp_syn_sent 1 MAXINT 480 tcp_time_wait 1 MAXINT 480 tcp_timeout 1 MAXINT 480 udp_ack_timeout 1 MAXINT 24 udp_timeout 1 MAXINT 240 update_ipid 0 1 0 .fi .SH Calling out to internal functions .PP IPFilter provides a pair of functions that can be called from a rule that allow for a single rule to jump out to a group rather than walk through a list of rules to find the group. If you've got multiple networks, each with its own group of rules, this feature may help provide better filtering performance. .PP The lookup to find which rule group to jump to is done on either the source address or the destination address but not both. .PP In this example below, we are blocking all packets by default but then doing a lookup on the source address from group 1010. The two rules in the ipf.conf section are lone members of their group. For an incoming packet that is from 1.1.1.1, it will go through three rules: (1) the block rule, (2) the call rule and (3) the pass rule for group 1020. For a packet that is from 3.3.2.2, it will also go through three rules: (1) the block rule, (2) the call rule and (3) the pass rule for group 1030. Should a packet from 3.1.1.1 arrive, it will be blocked as it does not match any of the entries in group 1010, leaving it to only match the first rule. .PP .nf from ipf.conf ------------- block in all call now srcgrpmap/1010 in all pass in proto tcp from any to any port = 80 group 1020 pass in proto icmp all icmp-type echo group 1030 from ippool.conf ---------------- group-map in role=ipf number=1010 { 1.1.1.1 group = 1020, 3.3.0.0/16 group = 1030; }; .fi .SS IPFilter matching expressions .PP An experimental feature that has been added to filter rules is to use the same expression matching that is available with various commands to flush and list state/NAT table entries. The use of such an expression precludes the filter rule from using the normal IP header matching. .PP .nf pass in exp { "tcp.sport 23 or tcp.sport 50" } keep state .fi .SS Filter rules with BPF .PP On platforms that have the BPF built into the kernel, IPFilter can be built to allow BPF expressions in filter rules. This allows for packet matching to be on arbitrary data in the packt. The use of a BPF expression replaces all of the other protocol header matching done by IPFilter. .PP .nf pass in bpf-v4 { "tcp and (src port 23 or src port 50)" } \\ keep state .fi .PP These rules tend to be write-only because the act of compiling the filter expression into the BPF instructions loaded into the kernel can make it difficut to accurately reconstruct the original text filter. The end result is that while ipf.conf() can be easy to read, understanding the output from ipfstat might not be. .SH VARIABLES .PP This configuration file, like all others used with IPFilter, supports the use of variable substitution throughout the text. .PP .nf nif="ppp0"; pass in on $nif from any to any .fi .PP would become .PP .nf pass in on ppp0 from any to any .fi .PP Variables can be used recursively, such as 'foo="$bar baz";', so long as $bar exists when the parser reaches the assignment for foo. .PP See .B ipf(8) for instructions on how to define variables to be used from a shell environment. .DT .SH FILES /dev/ipf /etc/ipf.conf .br /usr/share/examples/ipfilter Directory with examples. .SH SEE ALSO ipf(8), ipfstat(8), ippool.conf(5), ippool(8) diff --git a/sbin/ipf/ipf/ipf.c b/sbin/ipf/ipf/ipf.c index 3567a82484fb..0cd393f37d5e 100644 --- a/sbin/ipf/ipf/ipf.c +++ b/sbin/ipf/ipf/ipf.c @@ -1,578 +1,578 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" #include #include #include #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$"; #endif #if !defined(__SVR4) && defined(__GNUC__) extern char *index(const char *, int); #endif extern char *optarg; extern int optind; extern frentry_t *frtop; void ipf_frsync(void); void zerostats(void); int main(int, char *[]); int opts = 0; int outputc = 0; int use_inet6 = 0; int exitstatus = 0; static void procfile(char *); static void flushfilter(char *, int *); static void set_state(u_int); static void showstats(friostat_t *); static void packetlogon(char *); static void swapactive(void); static int opendevice(char *, int); static void closedevice(void); static char *ipfname = IPL_NAME; static void usage(void); static int showversion(void); static int get_flags(void); static int ipf_interceptadd(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() { fprintf(stderr, "usage: ipf [-6AdDEInoPrRsvVyzZ] %s %s %s\n", "[-l block|pass|nomatch|state|nat]", "[-cc] [-F i|o|a|s|S|u]", "[-f filename] [-T ]"); exit(1); } int main(int argc, char *argv[]) { int c, *filter = NULL; if (argc < 2) usage(); assigndefined(getenv("IPF_PREDEFINED")); while ((c = getopt(argc, argv, "46Ac:dDEf:F:Il:m:noPrRsT:vVyzZ")) != -1) { switch (c) { case '?' : usage(); break; case '4' : use_inet6 = -1; break; case '6' : use_inet6 = 1; break; case 'A' : opts &= ~OPT_INACTIVE; break; case 'c' : if (strcmp(optarg, "c") == 0) outputc = 1; break; case 'E' : set_state((u_int)1); break; case 'D' : set_state((u_int)0); break; case 'd' : opts ^= OPT_DEBUG; break; case 'f' : procfile(optarg); break; case 'F' : flushfilter(optarg, filter); break; case 'I' : opts ^= OPT_INACTIVE; break; case 'l' : packetlogon(optarg); break; case 'm' : filter = parseipfexpr(optarg, NULL); break; case 'n' : opts ^= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : break; case 'P' : ipfname = IPAUTH_NAME; break; case 'R' : opts ^= OPT_NORESOLVE; break; case 'r' : opts ^= OPT_REMOVE; break; case 's' : swapactive(); break; case 'T' : if (opendevice(ipfname, 1) >= 0) ipf_dotuning(fd, optarg, ioctl); break; case 'v' : opts += OPT_VERBOSE; break; case 'V' : if (showversion()) exit(1); break; case 'y' : ipf_frsync(); break; case 'z' : opts ^= OPT_ZERORULEST; break; case 'Z' : zerostats(); break; } } if (optind < 2) usage(); if (fd != -1) (void) close(fd); return(exitstatus); /* NOTREACHED */ } static int opendevice(char *ipfdev, int check) { if (opts & OPT_DONOTHING) - return -2; + return(-2); if (check && checkrev(ipfname) == -1) { fprintf(stderr, "User/kernel version check failed\n"); - return -2; + return(-2); } if (!ipfdev) ipfdev = ipfname; if (fd == -1) if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) ipferror(fd, "open device"); - return fd; + return(fd); } static void closedevice(void) { close(fd); fd = -1; } static int get_flags(void) { int i = 0; if ((opendevice(ipfname, 1) != -2) && (ioctl(fd, SIOCGETFF, &i) == -1)) { ipferror(fd, "SIOCGETFF"); - return 0; + return(0); } - return i; + return(i); } static void set_state(u_int enable) { if (opendevice(ipfname, 0) != -2) { if (ioctl(fd, SIOCFRENB, &enable) == -1) { if (errno == EBUSY) { fprintf(stderr, "IP FIlter: already initialized\n"); } else { ipferror(fd, "SIOCFRENB"); } } } return; } static void procfile(char *file) { (void) opendevice(ipfname, 1); initparse(); ipf_parsefile(fd, ipf_interceptadd, iocfunctions, file); if (outputc) { printC(0); printC(1); emit(-1, -1, NULL, NULL); } } static int ipf_interceptadd(int fd, ioctlfunc_t ioctlfunc, void *ptr) { if (outputc) printc(ptr); if (ipf_addrule(fd, ioctlfunc, ptr) != 0) exitstatus = 1; - return 0; + return(0); } static void packetlogon(char *opt) { int flag, xfd, logopt, change = 0; flag = get_flags(); if (flag != 0) { if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) printf("log flag is currently %#x\n", flag); } flag &= ~(FF_LOGPASS|FF_LOGNOMATCH|FF_LOGBLOCK); if (strstr(opt, "pass")) { flag |= FF_LOGPASS; if (opts & OPT_VERBOSE) printf("set log flag: pass\n"); change = 1; } if (strstr(opt, "nomatch")) { flag |= FF_LOGNOMATCH; if (opts & OPT_VERBOSE) printf("set log flag: nomatch\n"); change = 1; } if (strstr(opt, "block") || strchr(opt, 'd')) { flag |= FF_LOGBLOCK; if (opts & OPT_VERBOSE) printf("set log flag: block\n"); change = 1; } if (strstr(opt, "none")) { if (opts & OPT_VERBOSE) printf("disable all log flags\n"); change = 1; } if (change == 1) { if (opendevice(ipfname, 1) != -2 && (ioctl(fd, SIOCSETFF, &flag) != 0)) ipferror(fd, "ioctl(SIOCSETFF)"); } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { flag = get_flags(); printf("log flags are now %#x\n", flag); } if (strstr(opt, "state")) { if (opts & OPT_VERBOSE) printf("set state log flag\n"); xfd = open(IPSTATE_NAME, O_RDWR); if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) ipferror(fd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } } if (strstr(opt, "nat")) { if (opts & OPT_VERBOSE) printf("set nat log flag\n"); xfd = open(IPNAT_NAME, O_RDWR); if (xfd >= 0) { logopt = 0; if (ioctl(xfd, SIOCGETLG, &logopt)) ipferror(xfd, "ioctl(SIOCGETLG)"); else { logopt = 1 - logopt; if (ioctl(xfd, SIOCSETLG, &logopt)) ipferror(xfd, "ioctl(SIOCSETLG)"); } close(xfd); } } } static void flushfilter(char *arg, int *filter) { int fl = 0, rem; if (!arg || !*arg) return; if (!strcmp(arg, "s") || !strcmp(arg, "S") || ISDIGIT(*arg)) { if (*arg == 'S') fl = 0; else if (*arg == 's') fl = 1; else fl = atoi(arg); rem = fl; closedevice(); if (opendevice(IPSTATE_NAME, 1) == -2) exit(1); if (!(opts & OPT_DONOTHING)) { if (use_inet6) { 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) { ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s (%d)\n", arg, rem); } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { printf("%d state entries removed\n", fl); } closedevice(); return; } else if (strchr(arg, 'i') || strchr(arg, 'I')) fl = FR_INQUE; else if (strchr(arg, 'o') || strchr(arg, 'O')) fl = FR_OUTQUE; else if (strchr(arg, 'a') || strchr(arg, 'A')) fl = FR_OUTQUE|FR_INQUE; else { fprintf(stderr, "Incorrect flush argument: %s\n", arg); usage(); } if (opts & OPT_INACTIVE) fl |= FR_INACTIVE; rem = fl; if (opendevice(ipfname, 1) == -2) exit(1); if (!(opts & OPT_DONOTHING)) { if (use_inet6) { if (ioctl(fd, SIOCIPFL6, &fl) == -1) { ipferror(fd, "ioctl(SIOCIPFL6)"); exit(1); } } else { if (ioctl(fd, SIOCIPFFL, &fl) == -1) { ipferror(fd, "ioctl(SIOCIPFFL)"); exit(1); } } } if ((opts & (OPT_DONOTHING|OPT_DEBUG)) == OPT_DEBUG) { printf("remove flags %s%s (%d)\n", (rem & FR_INQUE) ? "I" : "", (rem & FR_OUTQUE) ? "O" : "", rem); } if ((opts & (OPT_DONOTHING|OPT_VERBOSE)) == OPT_VERBOSE) { printf("%d filter rules removed\n", fl); } return; } static void swapactive(void) { int in = 2; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCSWAPA, &in) == -1) ipferror(fd, "ioctl(SIOCSWAPA)"); else printf("Set %d now inactive\n", in); } void ipf_frsync(void) { int frsyn = 0; if (opendevice(ipfname, 1) != -2 && ioctl(fd, SIOCFRSYN, &frsyn) == -1) ipferror(fd, "SIOCFRSYN"); else printf("filter sync'd\n"); } void zerostats(void) { ipfobj_t obj; friostat_t fio; obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_IPFSTAT; obj.ipfo_size = sizeof(fio); obj.ipfo_ptr = &fio; obj.ipfo_offset = 0; if (opendevice(ipfname, 1) != -2) { if (ioctl(fd, SIOCFRZST, &obj) == -1) { ipferror(fd, "ioctl(SIOCFRZST)"); exit(-1); } showstats(&fio); } } /* * read the kernel stats for packets blocked and passed */ static void showstats(friostat_t *fp) { printf("bad packets:\t\tin %lu\tout %lu\n", fp->f_st[0].fr_bad, fp->f_st[1].fr_bad); 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\n", fp->f_st[0].fr_acct); 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\n", fp->f_st[0].fr_acct); 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); } static int showversion(void) { struct friostat fio; ipfobj_t ipfo; u_32_t flags; char *s; int vfd; bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_size = sizeof(fio); ipfo.ipfo_ptr = (void *)&fio; ipfo.ipfo_type = IPFOBJ_IPFSTAT; printf("ipf: %s (%d)\n", IPL_VERSION, (int)sizeof(frentry_t)); if ((vfd = open(ipfname, O_RDONLY)) == -1) { perror("open device"); - return 1; + return(1); } if (ioctl(vfd, SIOCGETFS, &ipfo)) { ipferror(vfd, "ioctl(SIOCGETFS)"); close(vfd); - return 1; + return(1); } close(vfd); flags = get_flags(); printf("Kernel: %-*.*s\n", (int)sizeof(fio.f_version), (int)sizeof(fio.f_version), fio.f_version); printf("Running: %s\n", (fio.f_running > 0) ? "yes" : "no"); printf("Log Flags: %#x = ", flags); s = ""; if (flags & FF_LOGPASS) { printf("pass"); s = ", "; } if (flags & FF_LOGBLOCK) { printf("%sblock", s); s = ", "; } if (flags & FF_LOGNOMATCH) { printf("%snomatch", s); s = ", "; } if (flags & FF_BLOCKNONIP) { printf("%snonip", s); s = ", "; } if (!*s) printf("none set"); putchar('\n'); printf("Default: "); if (FR_ISPASS(fio.f_defpass)) s = "pass"; else if (FR_ISBLOCK(fio.f_defpass)) s = "block"; else s = "nomatch -> block"; printf("%s all, Logging: %savailable\n", s, fio.f_logging ? "" : "un"); printf("Active list: %d\n", fio.f_active); printf("Feature mask: %#x\n", fio.f_features); - return 0; + return(0); } diff --git a/sbin/ipf/ipf/ipfcomp.c b/sbin/ipf/ipf/ipfcomp.c index 105ff2b852e8..19a61c8bb0e0 100644 --- a/sbin/ipf/ipf/ipfcomp.c +++ b/sbin/ipf/ipf/ipfcomp.c @@ -1,1355 +1,1372 @@ /* $FreeBSD$ */ /* * 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$"; #endif #include "ipf.h" typedef struct { int c; int e; int n; int p; int s; } mc_t; static char *portcmp[] = { "*", "==", "!=", "<", ">", "<=", ">=", "**", "***" }; static int count = 0; int intcmp(const void *, const void *); static void indent(FILE *, int); static void printeq(FILE *, char *, int, int, int); static void printipeq(FILE *, char *, int, int, int); static void addrule(FILE *, frentry_t *); static void printhooks(FILE *, int, int, frgroup_t *); static void emitheader(frgroup_t *, u_int, u_int); static void emitGroup(int, int, void *, frentry_t *, char *, u_int, u_int); static void emittail(void); static void printCgroup(int, frentry_t *, mc_t *, char *); #define FRC_IFN 0 #define FRC_V 1 #define FRC_P 2 #define FRC_FL 3 #define FRC_TOS 4 #define FRC_TTL 5 #define FRC_SRC 6 #define FRC_DST 7 #define FRC_TCP 8 #define FRC_SP 9 #define FRC_DP 10 #define FRC_OPT 11 #define FRC_SEC 12 #define FRC_ATH 13 #define FRC_ICT 14 #define FRC_ICC 15 #define FRC_MAX 16 static FILE *cfile = NULL; /* * This is called once per filter rule being loaded to emit data structures * required. */ -void -printc(frentry_t *fr) +void printc(fr) + frentry_t *fr; { u_long *ulp; char *and; FILE *fp; int i; if (fr->fr_family == 6) return; if ((fr->fr_type != FR_T_IPF) && (fr->fr_type != FR_T_NONE)) return; if ((fr->fr_type == FR_T_IPF) && ((fr->fr_datype != FRI_NORMAL) || (fr->fr_satype != FRI_NORMAL))) return; if (cfile == NULL) cfile = fopen("ip_rules.c", "w"); if (cfile == NULL) return; fp = cfile; if (count == 0) { fprintf(fp, "/*\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"); fprintf(fp, "* to the original author and the contributors.\n"); fprintf(fp, "*/\n\n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#if (__FreeBSD_version >= 40000)\n"); fprintf(fp, "# if defined(_KERNEL)\n"); fprintf(fp, "# include \n"); fprintf(fp, "# else\n"); fprintf(fp, "# include \n"); fprintf(fp, "# endif\n"); fprintf(fp, "#endif\n"); fprintf(fp, "#if (__NetBSD_Version__ >= 399000000)\n"); fprintf(fp, "#else\n"); fprintf(fp, "# if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)\n"); fprintf(fp, "# include \n"); fprintf(fp, "# endif\n"); fprintf(fp, "#endif\n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)\n"); fprintf(fp, "# include \n"); fprintf(fp, "#endif\n"); fprintf(fp, "#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)\n"); fprintf(fp, "# include \n"); fprintf(fp, "#else\n"); fprintf(fp, "# include \n"); fprintf(fp, "#endif /* FreeBSD */\n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \"netinet/ip_compat.h\"\n"); fprintf(fp, "#include \"netinet/ip_fil.h\"\n\n"); fprintf(fp, "#include \"netinet/ip_rules.h\"\n\n"); fprintf(fp, "#ifndef _KERNEL\n"); fprintf(fp, "# include \n"); 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); fr->fr_type |= FR_T_BUILTIN; and = ""; fr->fr_ref = 1; i = sizeof(*fr); if (i & -(1 - sizeof(*ulp))) i += sizeof(u_long); for (i /= sizeof(u_long), ulp = (u_long *)fr; i > 0; i--) { fprintf(fp, "%s%#lx", and, *ulp++); and = ", "; } fprintf(fp, "\n};\n"); fr->fr_type &= ~FR_T_BUILTIN; count++; fflush(fp); } static frgroup_t *groups = NULL; -static void -addrule(FILE *fp, frentry_t *fr) +static void addrule(fp, fr) + FILE *fp; + frentry_t *fr; { frentry_t *f, **fpp; frgroup_t *g; u_long *ulp; char *ghead; char *gname; char *and; int i; f = (frentry_t *)malloc(sizeof(*f)); bcopy((char *)fr, (char *)f, sizeof(*fr)); if (fr->fr_ipf) { f->fr_ipf = (fripf_t *)malloc(sizeof(*f->fr_ipf)); bcopy((char *)fr->fr_ipf, (char *)f->fr_ipf, sizeof(*fr->fr_ipf)); } f->fr_next = NULL; gname = FR_NAME(fr, fr_group); for (g = groups; g != NULL; g = g->fg_next) if ((strncmp(g->fg_name, gname, FR_GROUPLEN) == 0) && (g->fg_flags == (f->fr_flags & FR_INOUT))) break; if (g == NULL) { g = (frgroup_t *)calloc(1, sizeof(*g)); g->fg_next = groups; groups = g; g->fg_head = f; strncpy(g->fg_name, gname, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } for (fpp = &g->fg_start; *fpp != NULL; ) fpp = &((*fpp)->fr_next); *fpp = f; if (fr->fr_dsize > 0) { fprintf(fp, "\ static u_long ipf%s_rule_data_%s_%u[] = {\n", f->fr_flags & FR_INQUE ? "in" : "out", g->fg_name, g->fg_ref); and = ""; i = fr->fr_dsize; ulp = fr->fr_data; for (i /= sizeof(u_long); i > 0; i--) { fprintf(fp, "%s%#lx", and, *ulp++); and = ", "; } fprintf(fp, "\n};\n"); } fprintf(fp, "\nstatic u_long %s_rule_%s_%d[] = {\n", f->fr_flags & FR_INQUE ? "in" : "out", g->fg_name, g->fg_ref); g->fg_ref++; 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, ghead, FR_GROUPLEN) == 0) && g->fg_flags == (f->fr_flags & FR_INOUT)) break; if (g == NULL) { g = (frgroup_t *)calloc(1, sizeof(*g)); g->fg_next = groups; groups = g; g->fg_head = f; strncpy(g->fg_name, ghead, FR_GROUPLEN); g->fg_ref = 0; g->fg_flags = f->fr_flags & FR_INOUT; } } } -int -intcmp(const void *c1, const void *c2) +int intcmp(c1, c2) + const void *c1, *c2; { const mc_t *i1 = (const mc_t *)c1, *i2 = (const mc_t *)c2; if (i1->n == i2->n) { - return i1->c - i2->c; + return(i1->c - i2->c); } - return i2->n - i1->n; + return(i2->n - i1->n); } -static void -indent(FILE *fp, int in) +static void indent(fp, in) + FILE *fp; + int in; { for (; in; in--) fputc('\t', fp); } -static void -printeq(FILE *fp, char *var, int m, int max, int v) +static void printeq(fp, var, m, max, v) + FILE *fp; + char *var; + int m, max, v; { if (m == max) fprintf(fp, "%s == %#x) {\n", var, v); else fprintf(fp, "(%s & %#x) == %#x) {\n", var, m, v); } /* * Parameters: var - IP# being compared * fl - 0 for positive match, 1 for negative match * m - netmask * v - required address */ -static void -printipeq(FILE *fp, char *var, int fl, int m, int v) +static void printipeq(fp, var, fl, m, v) + FILE *fp; + char *var; + int fl, m, v; { if (m == 0xffffffff) fprintf(fp, "%s ", var); else fprintf(fp, "(%s & %#x) ", var, m); fprintf(fp, "%c", fl ? '!' : '='); fprintf(fp, "= %#x) {\n", v); } -void -emit(int num, int dir, void *v, frentry_t *fr) +void emit(num, dir, v, fr) + int num, dir; + void *v; + frentry_t *fr; { u_int incnt, outcnt; frgroup_t *g; frentry_t *f; for (g = groups; g != NULL; g = g->fg_next) { if (dir == 0 || dir == -1) { if ((g->fg_flags & FR_INQUE) == 0) continue; for (incnt = 0, f = g->fg_start; f != NULL; f = f->fr_next) incnt++; emitGroup(num, dir, v, fr, g->fg_name, incnt, 0); } if (dir == 1 || dir == -1) { if ((g->fg_flags & FR_OUTQUE) == 0) continue; for (outcnt = 0, f = g->fg_start; f != NULL; f = f->fr_next) outcnt++; emitGroup(num, dir, v, fr, g->fg_name, 0, outcnt); } } if (num == -1 && dir == -1) { for (g = groups; g != NULL; g = g->fg_next) { if ((g->fg_flags & FR_INQUE) != 0) { for (incnt = 0, f = g->fg_start; f != NULL; f = f->fr_next) incnt++; if (incnt > 0) emitheader(g, incnt, 0); } if ((g->fg_flags & FR_OUTQUE) != 0) { for (outcnt = 0, f = g->fg_start; f != NULL; f = f->fr_next) outcnt++; if (outcnt > 0) emitheader(g, 0, outcnt); } } emittail(); fprintf(cfile, "#endif /* IPFILTER_COMPILED */\n"); } } -static void -emitheader(frgroup_t *grp, u_int incount, u_int outcount) +static void emitheader(grp, incount, outcount) + frgroup_t *grp; + u_int incount, outcount; { static FILE *fph = NULL; frgroup_t *g; if (fph == NULL) { fph = fopen("ip_rules.h", "w"); if (fph == NULL) return; fprintf(fph, "extern int ipfrule_add(void));\n"); fprintf(fph, "extern int ipfrule_remove(void));\n"); } printhooks(cfile, incount, outcount, grp); if (incount) { fprintf(fph, "\n\ extern frentry_t *ipfrule_match_in_%s(fr_info_t *, u_32_t *));\n\ extern frentry_t *ipf_rules_in_%s[%d];\n", grp->fg_name, grp->fg_name, incount); for (g = groups; g != grp; g = g->fg_next) if ((strncmp(g->fg_name, grp->fg_name, FR_GROUPLEN) == 0) && g->fg_flags == grp->fg_flags) break; if (g == grp) { fprintf(fph, "\n\ extern int ipfrule_add_in_%s(void));\n\ extern int ipfrule_remove_in_%s(void));\n", grp->fg_name, grp->fg_name); } } if (outcount) { fprintf(fph, "\n\ extern frentry_t *ipfrule_match_out_%s(fr_info_t *, u_32_t *));\n\ extern frentry_t *ipf_rules_out_%s[%d];\n", grp->fg_name, grp->fg_name, outcount); for (g = groups; g != grp; g = g->fg_next) if ((strncmp(g->fg_name, grp->fg_name, FR_GROUPLEN) == 0) && g->fg_flags == grp->fg_flags) break; if (g == grp) { fprintf(fph, "\n\ extern int ipfrule_add_out_%s(void));\n\ extern int ipfrule_remove_out_%s(void));\n", grp->fg_name, grp->fg_name); } } } -static void -emittail(void) +static void emittail() { frgroup_t *g; fprintf(cfile, "\n\ int ipfrule_add()\n\ {\n\ int err;\n\ \n"); for (g = groups; g != NULL; g = g->fg_next) fprintf(cfile, "\ err = ipfrule_add_%s_%s();\n\ if (err != 0)\n\ - return err;\n", + return(err);\n", (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name); fprintf(cfile, "\ - return 0;\n"); + return(0);\n"); fprintf(cfile, "}\n\ \n"); fprintf(cfile, "\n\ int ipfrule_remove()\n\ {\n\ int err;\n\ \n"); for (g = groups; g != NULL; g = g->fg_next) fprintf(cfile, "\ err = ipfrule_remove_%s_%s();\n\ if (err != 0)\n\ - return err;\n", + return(err);\n", (g->fg_flags & FR_INQUE) ? "in" : "out", g->fg_name); fprintf(cfile, "\ - return 0;\n"); + return(0);\n"); fprintf(cfile, "}\n"); } -static void -emitGroup(int num, int dir, void *v, frentry_t *fr, char *group, - u_int incount, u_int outcount) +static void emitGroup(num, dir, v, fr, group, 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 }; static char egroup[FR_GROUPLEN] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static int openfunc = 0; static mc_t *n = NULL; static int sin = 0; frentry_t *f; frgroup_t *g; fripf_t *ipf; int i, in, j; mc_t *m = v; if (fp == NULL) fp = cfile; if (fp == NULL) return; if (strncmp(egroup, group, FR_GROUPLEN)) { for (sin--; sin > 0; sin--) { indent(fp, sin); fprintf(fp, "}\n"); } if (openfunc == 1) { - fprintf(fp, "\treturn fr;\n}\n"); + fprintf(fp, "\treturn(fr);\n}\n"); openfunc = 0; if (n != NULL) { free(n); n = NULL; } } sin = 0; header[0] = 0; header[1] = 0; strncpy(egroup, group, FR_GROUPLEN); } else if (openfunc == 1 && num < 0) { if (n != NULL) { free(n); n = NULL; } for (sin--; sin > 0; sin--) { indent(fp, sin); fprintf(fp, "}\n"); } if (openfunc == 1) { - fprintf(fp, "\treturn fr;\n}\n"); + fprintf(fp, "\treturn(fr);\n}\n"); openfunc = 0; } } if (dir == -1) return; for (g = groups; g != NULL; g = g->fg_next) { if (dir == 0 && (g->fg_flags & FR_INQUE) == 0) continue; else if (dir == 1 && (g->fg_flags & FR_OUTQUE) == 0) continue; if (strncmp(g->fg_name, group, FR_GROUPLEN) != 0) continue; break; } /* * Output the array of pointers to rules for this group. */ if (g != NULL && num == -2 && dir == 0 && header[0] == 0 && incount != 0) { fprintf(fp, "\nfrentry_t *ipf_rules_in_%s[%d] = {", group, incount); for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { if ((f->fr_flags & FR_INQUE) == 0) continue; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } fprintf(fp, "(frentry_t *)&in_rule_%s_%d", FR_NAME(f, fr_group), i); if (i + 1 < incount) fprintf(fp, ", "); i++; } fprintf(fp, "\n};\n"); } if (g != NULL && num == -2 && dir == 1 && header[0] == 0 && outcount != 0) { fprintf(fp, "\nfrentry_t *ipf_rules_out_%s[%d] = {", group, outcount); for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { if ((f->fr_flags & FR_OUTQUE) == 0) continue; if ((i & 1) == 0) { fprintf(fp, "\n\t"); } fprintf(fp, "(frentry_t *)&out_rule_%s_%d", FR_NAME(f, fr_group), i); if (i + 1 < outcount) fprintf(fp, ", "); i++; } fprintf(fp, "\n};\n"); fp = NULL; } if (num < 0) return; in = 0; ipf = fr->fr_ipf; /* * If the function header has not been printed then print it now. */ if (g != NULL && header[dir] == 0) { int pdst = 0, psrc = 0; openfunc = 1; fprintf(fp, "\nfrentry_t *ipfrule_match_%s_%s(fin, passp)\n", (dir == 0) ? "in" : "out", group); fprintf(fp, "fr_info_t *fin;\n"); fprintf(fp, "u_32_t *passp;\n"); fprintf(fp, "{\n"); fprintf(fp, "\tfrentry_t *fr = NULL;\n"); /* * Print out any variables that need to be declared. */ for (f = g->fg_start, i = 0; f != NULL; f = f->fr_next) { if (incount + outcount > m[FRC_SRC].e + 1) psrc = 1; if (incount + outcount > m[FRC_DST].e + 1) pdst = 1; } if (psrc == 1) fprintf(fp, "\tu_32_t src = ntohl(%s);\n", "fin->fin_fi.fi_saddr"); if (pdst == 1) fprintf(fp, "\tu_32_t dst = ntohl(%s);\n", "fin->fin_fi.fi_daddr"); } for (i = 0; i < FRC_MAX; i++) { switch(m[i].c) { case FRC_IFN : if (fr->fr_ifnames[0] != -1) m[i].s = 1; break; case FRC_V : if (ipf != NULL && ipf->fri_mip.fi_v != 0) m[i].s = 1; break; case FRC_FL : if (ipf != NULL && ipf->fri_mip.fi_flx != 0) m[i].s = 1; break; case FRC_P : if (ipf != NULL && ipf->fri_mip.fi_p != 0) m[i].s = 1; break; case FRC_TTL : if (ipf != NULL && ipf->fri_mip.fi_ttl != 0) m[i].s = 1; break; case FRC_TOS : if (ipf != NULL && ipf->fri_mip.fi_tos != 0) m[i].s = 1; break; case FRC_TCP : if (ipf == NULL) break; if ((ipf->fri_ip.fi_p == IPPROTO_TCP) && fr->fr_tcpfm != 0) m[i].s = 1; break; case FRC_SP : if (ipf == NULL) break; if (fr->fr_scmp == FR_INRANGE) m[i].s = 1; else if (fr->fr_scmp == FR_OUTRANGE) m[i].s = 1; else if (fr->fr_scmp != 0) m[i].s = 1; break; case FRC_DP : if (ipf == NULL) break; if (fr->fr_dcmp == FR_INRANGE) m[i].s = 1; else if (fr->fr_dcmp == FR_OUTRANGE) m[i].s = 1; else if (fr->fr_dcmp != 0) m[i].s = 1; break; case FRC_SRC : if (ipf == NULL) break; if (fr->fr_satype == FRI_LOOKUP) { ; } else if ((fr->fr_smask != 0) || (fr->fr_flags & FR_NOTSRCIP) != 0) m[i].s = 1; break; case FRC_DST : if (ipf == NULL) break; if (fr->fr_datype == FRI_LOOKUP) { ; } else if ((fr->fr_dmask != 0) || (fr->fr_flags & FR_NOTDSTIP) != 0) m[i].s = 1; break; case FRC_OPT : if (ipf == NULL) break; if (fr->fr_optmask != 0) m[i].s = 1; break; case FRC_SEC : if (ipf == NULL) break; if (fr->fr_secmask != 0) m[i].s = 1; break; case FRC_ATH : if (ipf == NULL) break; if (fr->fr_authmask != 0) m[i].s = 1; break; case FRC_ICT : if (ipf == NULL) break; if ((fr->fr_icmpm & 0xff00) != 0) m[i].s = 1; break; case FRC_ICC : if (ipf == NULL) break; if ((fr->fr_icmpm & 0xff) != 0) m[i].s = 1; break; } } if (!header[dir]) { fprintf(fp, "\n"); header[dir] = 1; sin = 0; } qsort(m, FRC_MAX, sizeof(mc_t), intcmp); if (n) { /* * Calculate the indentation interval upto the last common * common comparison being made. */ for (i = 0, in = 1; i < FRC_MAX; i++) { if (n[i].c != m[i].c) break; if (n[i].s != m[i].s) break; if (n[i].s) { if (n[i].n && (n[i].n > n[i].e)) { m[i].p++; in += m[i].p; break; } if (n[i].e > 0) { in++; } else break; } } if (sin != in) { for (j = sin - 1; j >= in; j--) { indent(fp, j); fprintf(fp, "}\n"); } } } else { in = 1; i = 0; } /* * print out C code that implements a filter rule. */ for (; i < FRC_MAX; i++) { switch(m[i].c) { case FRC_IFN : if (m[i].s) { indent(fp, in); fprintf(fp, "if (fin->fin_ifp == "); fprintf(fp, "ipf_rules_%s_%s[%d]->fr_ifa) {\n", dir ? "out" : "in", group, num); in++; } break; case FRC_V : if (m[i].s) { indent(fp, in); fprintf(fp, "if (fin->fin_v == %d) {\n", ipf->fri_ip.fi_v); in++; } break; case FRC_FL : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_flx", ipf->fri_mip.fi_flx, 0xf, ipf->fri_ip.fi_flx); in++; } break; case FRC_P : if (m[i].s) { indent(fp, in); fprintf(fp, "if (fin->fin_p == %d) {\n", ipf->fri_ip.fi_p); in++; } break; case FRC_TTL : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_ttl", ipf->fri_mip.fi_ttl, 0xff, ipf->fri_ip.fi_ttl); in++; } break; case FRC_TOS : if (m[i].s) { indent(fp, in); fprintf(fp, "if (fin->fin_tos"); printeq(fp, "fin->fin_tos", ipf->fri_mip.fi_tos, 0xff, ipf->fri_ip.fi_tos); in++; } break; case FRC_TCP : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_tcpf", fr->fr_tcpfm, 0xff, fr->fr_tcpf); in++; } break; case FRC_SP : if (!m[i].s) break; if (fr->fr_scmp == FR_INRANGE) { indent(fp, in); fprintf(fp, "if ((fin->fin_data[0] > %d) && ", fr->fr_sport); fprintf(fp, "(fin->fin_data[0] < %d)", fr->fr_stop); fprintf(fp, ") {\n"); in++; } else if (fr->fr_scmp == FR_OUTRANGE) { indent(fp, in); fprintf(fp, "if ((fin->fin_data[0] < %d) || ", fr->fr_sport); fprintf(fp, "(fin->fin_data[0] > %d)", fr->fr_stop); fprintf(fp, ") {\n"); in++; } else if (fr->fr_scmp) { indent(fp, in); fprintf(fp, "if (fin->fin_data[0] %s %d)", portcmp[fr->fr_scmp], fr->fr_sport); fprintf(fp, " {\n"); in++; } break; case FRC_DP : if (!m[i].s) break; if (fr->fr_dcmp == FR_INRANGE) { indent(fp, in); fprintf(fp, "if ((fin->fin_data[1] > %d) && ", fr->fr_dport); fprintf(fp, "(fin->fin_data[1] < %d)", fr->fr_dtop); fprintf(fp, ") {\n"); in++; } else if (fr->fr_dcmp == FR_OUTRANGE) { indent(fp, in); fprintf(fp, "if ((fin->fin_data[1] < %d) || ", fr->fr_dport); fprintf(fp, "(fin->fin_data[1] > %d)", fr->fr_dtop); fprintf(fp, ") {\n"); in++; } else if (fr->fr_dcmp) { indent(fp, in); fprintf(fp, "if (fin->fin_data[1] %s %d)", portcmp[fr->fr_dcmp], fr->fr_dport); fprintf(fp, " {\n"); in++; } break; case FRC_SRC : if (!m[i].s) break; if (fr->fr_satype == FRI_LOOKUP) { ; } else if ((fr->fr_smask != 0) || (fr->fr_flags & FR_NOTSRCIP) != 0) { indent(fp, in); fprintf(fp, "if ("); printipeq(fp, "src", fr->fr_flags & FR_NOTSRCIP, fr->fr_smask, fr->fr_saddr); in++; } break; case FRC_DST : if (!m[i].s) break; if (fr->fr_datype == FRI_LOOKUP) { ; } else if ((fr->fr_dmask != 0) || (fr->fr_flags & FR_NOTDSTIP) != 0) { indent(fp, in); fprintf(fp, "if ("); printipeq(fp, "dst", fr->fr_flags & FR_NOTDSTIP, fr->fr_dmask, fr->fr_daddr); in++; } break; case FRC_OPT : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_fi.fi_optmsk", fr->fr_optmask, 0xffffffff, fr->fr_optbits); in++; } break; case FRC_SEC : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_fi.fi_secmsk", fr->fr_secmask, 0xffff, fr->fr_secbits); in++; } break; case FRC_ATH : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_fi.fi_authmsk", fr->fr_authmask, 0xffff, fr->fr_authbits); in++; } break; case FRC_ICT : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_data[0]", fr->fr_icmpm & 0xff00, 0xffff, fr->fr_icmp & 0xff00); in++; } break; case FRC_ICC : if (m[i].s) { indent(fp, in); fprintf(fp, "if ("); printeq(fp, "fin->fin_data[0]", fr->fr_icmpm & 0xff, 0xffff, fr->fr_icmp & 0xff); in++; } break; } } indent(fp, in); if (fr->fr_flags & FR_QUICK) { - fprintf(fp, "return (frentry_t *)&%s_rule_%s_%d;\n", + fprintf(fp, "return((frentry_t *)&%s_rule_%s_%d);\n", fr->fr_flags & FR_INQUE ? "in" : "out", 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_NAME(fr, fr_group), num); } if (n == NULL) n = (mc_t *)malloc(sizeof(*n) * FRC_MAX); bcopy((char *)m, (char *)n, sizeof(*n) * FRC_MAX); sin = in; } -void -printC(int dir) +void printC(dir) + int dir; { static mc_t *m = NULL; frgroup_t *g; if (m == NULL) m = (mc_t *)calloc(FRC_MAX, sizeof(*m)); for (g = groups; g != NULL; g = g->fg_next) { if ((dir == 0) && ((g->fg_flags & FR_INQUE) != 0)) printCgroup(dir, g->fg_start, m, g->fg_name); if ((dir == 1) && ((g->fg_flags & FR_OUTQUE) != 0)) printCgroup(dir, g->fg_start, m, g->fg_name); } emit(-1, dir, m, NULL); } /* * Now print out code to implement all of the rules. */ -static void -printCgroup(int dir, frentry_t *top, mc_t *m, char *group) +static void printCgroup(dir, top, m, group) + int dir; + frentry_t *top; + mc_t *m; + char *group; { frentry_t *fr, *fr1; int i, n, rn; u_int count; for (count = 0, fr1 = top; fr1 != NULL; fr1 = fr1->fr_next) { if ((dir == 0) && ((fr1->fr_flags & FR_INQUE) != 0)) count++; else if ((dir == 1) && ((fr1->fr_flags & FR_OUTQUE) != 0)) count++; } if (dir == 0) emitGroup(-2, dir, m, fr1, group, count, 0); else if (dir == 1) emitGroup(-2, dir, m, fr1, group, 0, count); /* * Before printing each rule, check to see how many of its fields are * matched by subsequent rules. */ for (fr1 = top, rn = 0; fr1 != NULL; fr1 = fr1->fr_next, rn++) { if (!dir && !(fr1->fr_flags & FR_INQUE)) continue; if (dir && !(fr1->fr_flags & FR_OUTQUE)) continue; n = 0xfffffff; for (i = 0; i < FRC_MAX; i++) m[i].e = 0; qsort(m, FRC_MAX, sizeof(mc_t), intcmp); for (i = 0; i < FRC_MAX; i++) { m[i].c = i; m[i].e = 0; m[i].n = 0; m[i].s = 0; } for (fr = fr1->fr_next; fr; fr = fr->fr_next) { if (!dir && !(fr->fr_flags & FR_INQUE)) continue; if (dir && !(fr->fr_flags & FR_OUTQUE)) continue; if ((n & 0x0001) && !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_family == fr->fr_family)) { m[FRC_V].e++; m[FRC_V].n++; } else n &= ~0x0002; if ((n & 0x0004) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_mip.fi_flx == fr->fr_mip.fi_flx) && (fr1->fr_ip.fi_flx == fr->fr_ip.fi_flx)) { m[FRC_FL].e++; m[FRC_FL].n++; } else n &= ~0x0004; if ((n & 0x0008) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_proto == fr->fr_proto)) { m[FRC_P].e++; m[FRC_P].n++; } else n &= ~0x0008; if ((n & 0x0010) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_ttl == fr->fr_ttl)) { m[FRC_TTL].e++; m[FRC_TTL].n++; } else n &= ~0x0010; if ((n & 0x0020) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_tos == fr->fr_tos)) { m[FRC_TOS].e++; m[FRC_TOS].n++; } else n &= ~0x0020; if ((n & 0x0040) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_tcpfm == fr->fr_tcpfm) && (fr1->fr_tcpf == fr->fr_tcpf))) { m[FRC_TCP].e++; m[FRC_TCP].n++; } else n &= ~0x0040; if ((n & 0x0080) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_scmp == fr->fr_scmp) && (fr1->fr_stop == fr->fr_stop) && (fr1->fr_sport == fr->fr_sport))) { m[FRC_SP].e++; m[FRC_SP].n++; } else n &= ~0x0080; if ((n & 0x0100) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_dcmp == fr->fr_dcmp) && (fr1->fr_dtop == fr->fr_dtop) && (fr1->fr_dport == fr->fr_dport))) { m[FRC_DP].e++; m[FRC_DP].n++; } else n &= ~0x0100; if ((n & 0x0200) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_satype == FRI_LOOKUP) && (fr->fr_satype == FRI_LOOKUP) && (fr1->fr_srcnum == fr->fr_srcnum))) { m[FRC_SRC].e++; m[FRC_SRC].n++; } else if ((n & 0x0200) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (((fr1->fr_flags & FR_NOTSRCIP) == (fr->fr_flags & FR_NOTSRCIP)))) { if ((fr1->fr_smask == fr->fr_smask) && (fr1->fr_saddr == fr->fr_saddr)) m[FRC_SRC].e++; else n &= ~0x0200; if (fr1->fr_smask && (fr1->fr_saddr & fr1->fr_smask) == (fr->fr_saddr & fr1->fr_smask)) { m[FRC_SRC].n++; n |= 0x0200; } } else { n &= ~0x0200; } if ((n & 0x0400) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_datype == FRI_LOOKUP) && (fr->fr_datype == FRI_LOOKUP) && (fr1->fr_dstnum == fr->fr_dstnum))) { m[FRC_DST].e++; m[FRC_DST].n++; } else if ((n & 0x0400) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (((fr1->fr_flags & FR_NOTDSTIP) == (fr->fr_flags & FR_NOTDSTIP)))) { if ((fr1->fr_dmask == fr->fr_dmask) && (fr1->fr_daddr == fr->fr_daddr)) m[FRC_DST].e++; else n &= ~0x0400; if (fr1->fr_dmask && (fr1->fr_daddr & fr1->fr_dmask) == (fr->fr_daddr & fr1->fr_dmask)) { m[FRC_DST].n++; n |= 0x0400; } } else { n &= ~0x0400; } if ((n & 0x0800) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_optmask == fr->fr_optmask) && (fr1->fr_optbits == fr->fr_optbits)) { m[FRC_OPT].e++; m[FRC_OPT].n++; } else n &= ~0x0800; if ((n & 0x1000) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_secmask == fr->fr_secmask) && (fr1->fr_secbits == fr->fr_secbits)) { m[FRC_SEC].e++; m[FRC_SEC].n++; } else n &= ~0x1000; if ((n & 0x10000) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && (fr1->fr_authmask == fr->fr_authmask) && (fr1->fr_authbits == fr->fr_authbits)) { m[FRC_ATH].e++; m[FRC_ATH].n++; } else n &= ~0x10000; if ((n & 0x20000) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_icmpm & 0xff00) == (fr->fr_icmpm & 0xff00)) && ((fr1->fr_icmp & 0xff00) == (fr->fr_icmp & 0xff00))) { m[FRC_ICT].e++; m[FRC_ICT].n++; } else n &= ~0x20000; if ((n & 0x40000) && (fr->fr_type == fr1->fr_type) && (fr->fr_type == FR_T_IPF) && ((fr1->fr_icmpm & 0xff) == (fr->fr_icmpm & 0xff)) && ((fr1->fr_icmp & 0xff) == (fr->fr_icmp & 0xff))) { m[FRC_ICC].e++; m[FRC_ICC].n++; } else n &= ~0x40000; } /*msort(m);*/ if (dir == 0) emitGroup(rn, dir, m, fr1, group, count, 0); else if (dir == 1) emitGroup(rn, dir, m, fr1, group, 0, count); } } -static void -printhooks(FILE *fp, int in, int out, frgroup_t *grp) +static void printhooks(fp, in, out, grp) + FILE *fp; + int in; + int out; + frgroup_t *grp; { frentry_t *fr; char *group; int dogrp, i; char *instr; group = grp->fg_name; dogrp = 0; if (in && out) { fprintf(stderr, "printhooks called with both in and out set\n"); exit(1); } if (in) { instr = "in"; } else if (out) { instr = "out"; } else { instr = "???"; } fprintf(fp, "static frentry_t ipfrule_%s_%s;\n", instr, group); fprintf(fp, "\ \n\ int ipfrule_add_%s_%s()\n", instr, group); fprintf(fp, "\ {\n\ int i, j, err = 0, max;\n\ frentry_t *fp;\n"); if (dogrp) fprintf(fp, "\ frgroup_t *fg;\n"); fprintf(fp, "\n"); for (i = 0, fr = grp->fg_start; fr != NULL; i++, fr = fr->fr_next) if (fr->fr_dsize > 0) { fprintf(fp, "\ ipf_rules_%s_%s[%d]->fr_data = &ipf%s_rule_data_%s_%u;\n", instr, grp->fg_name, i, instr, grp->fg_name, i); } fprintf(fp, "\ max = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *);\n\ for (i = 0; i < max; i++) {\n\ fp = ipf_rules_%s_%s[i];\n\ fp->fr_next = NULL;\n", instr, group, instr, group); fprintf(fp, "\ for (j = i + 1; j < max; j++)\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, instr, group, instr, group, instr, group, instr, group); if (dogrp) fprintf(fp, "\ \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"); fprintf(fp, "\ }\n\ \n\ fp = &ipfrule_%s_%s;\n", instr, group); fprintf(fp, "\ bzero((char *)fp, sizeof(*fp));\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); fprintf(fp, "\ fp->fr_dsize = sizeof(ipf_rules_%s_%s[0]);\n", instr, group); fprintf(fp, "\ fp->fr_family = AF_INET;\n\ fp->fr_func = (ipfunc_t)ipfrule_match_%s_%s;\n\ err = frrequest(&ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,\n\ ipfmain.ipf_active, 0);\n", instr, group); - fprintf(fp, "\treturn err;\n}\n"); + fprintf(fp, "\treturn(err);\n}\n"); fprintf(fp, "\n\n\ int ipfrule_remove_%s_%s()\n", instr, group); fprintf(fp, "\ {\n\ int err = 0, i;\n\ frentry_t *fp;\n\ \n\ /*\n\ * Try to remove the %sbound rule.\n", instr); fprintf(fp, "\ */\n\ if (ipfrule_%s_%s.fr_ref > 0) {\n", instr, group); fprintf(fp, "\ err = EBUSY;\n\ } else {\n"); fprintf(fp, "\ i = sizeof(ipf_rules_%s_%s)/sizeof(frentry_t *) - 1;\n\ for (; i >= 0; i--) {\n\ fp = ipf_rules_%s_%s[i];\n\ if (fp->fr_ref > 1) {\n\ err = EBUSY;\n\ break;\n\ }\n\ }\n\ }\n\ if (err == 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\ - return err;\n\ + return(err);\n\ \n\n"); - fprintf(fp, "\treturn err;\n}\n"); + fprintf(fp, "\treturn(err);\n}\n"); } diff --git a/sbin/ipf/ipf/ipl.4 b/sbin/ipf/ipf/ipl.4 index da1d9e61ce0f..696b2aa4533b 100644 --- a/sbin/ipf/ipf/ipl.4 +++ b/sbin/ipf/ipf/ipl.4 @@ -1,81 +1,81 @@ .\" $FreeBSD$ .\" .TH IPL 4 .SH NAME ipl \- IP packet log device .SH DESCRIPTION The \fBipl\fP pseudo device's purpose is to provide an easy way to gather packet headers of packets you wish to log. If a packet header is to be logged, the entire header is logged (including any IP options \- TCP/UDP options are not included when it calculates header size) or not at all. The packet contents are also logged after the header. If the log reader is busy or otherwise unable to read log records, up to IPLLOGSIZE (8192 is the default) bytes of data are stored. .PP Prepending every packet header logged is a structure containing information relevant to the packet following and why it was logged. The structure's format is as follows: .LP .nf /* * Log structure. Each packet header logged is prepended by one of these. * Following this in the log records read from the device will be an ipflog * structure which is then followed by any packet data. */ typedef struct iplog { u_long ipl_sec; u_long ipl_usec; u_int ipl_len; u_int ipl_count; size_t ipl_dsize; struct iplog *ipl_next; } iplog_t; typedef struct ipflog { #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) u_char fl_ifname[IFNAMSIZ]; #else u_int fl_unit; u_char fl_ifname[4]; #endif u_char fl_plen; /* extra data after hlen */ u_char fl_hlen; /* length of IP headers saved */ u_short fl_rule; /* assume never more than 64k rules, total */ u_32_t fl_flags; } ipflog_t; .fi .PP When reading from the \fBipl\fP device, it is necessary to call read(2) with a buffer big enough to hold at least 1 complete log record - reading of partial log records is not supported. .PP If the packet contents are more than 128 bytes when \fBlog body\fP is used, then only 128 bytes of the packet contents are logged. .PP Although it is only possible to read from the \fBipl\fP device, opening it for writing is required when using an ioctl which changes any kernel data. .PP The ioctls which are loaded with this device can be found under \fBipf(4)\fP. The ioctls which are for use with logging and don't affect the filter are: .LP .nf ioctl(fd, SIOCIPFFB, int *) ioctl(fd, FIONREAD, int *) .fi .PP The SIOCIPFFB ioctl flushes the log buffer and returns the number of bytes flushed. FIONREAD returns the number of bytes currently used for storing log data. If IPFILTER_LOG is not defined when compiling, SIOCIPFFB is not -available and FIONREAD will return but not do anything. +available( and FIONREAD will return but not do anything.); .PP There is currently no support for non-blocking IO with this device, meaning all read operations should be considered blocking in nature (if there is no data to read, it will sleep until some is made available). .SH SEE ALSO ipf(4) .SH BUGS Packet headers are dropped when the internal buffer (static size) fills. .SH FILES /dev/ipl0 diff --git a/sbin/ipf/ipfs/ipfs.c b/sbin/ipf/ipfs/ipfs.c index 680d2659ca51..e7e569153556 100644 --- a/sbin/ipf/ipfs/ipfs.c +++ b/sbin/ipf/ipfs/ipfs.c @@ -1,855 +1,855 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include #include #include #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipf.h" #include "netinet/ipl.h" #if !defined(lint) static const char rcsid[] = "@(#)$Id$"; #endif #ifndef IPF_SAVEDIR # define IPF_SAVEDIR "/var/db/ipf" #endif #ifndef IPF_NATFILE # define IPF_NATFILE "ipnat.ipf" #endif #ifndef IPF_STATEFILE # define IPF_STATEFILE "ipstate.ipf" #endif #if !defined(__SVR4) && defined(__GNUC__) extern char *index(const char *, int); #endif extern char *optarg; extern int optind; int main(int, char *[]); void usage(void); int changestateif(char *, char *); int changenatif(char *, char *); int readstate(int, char *); int readnat(int, char *); int writestate(int, char *); int opendevice(char *); void closedevice(int); int setlock(int, int); int writeall(char *); int readall(char *); int writenat(int, char *); int opts = 0; char *progname; void usage() { fprintf(stderr, "usage: %s [-nv] -l\n", progname); fprintf(stderr, "usage: %s [-nv] -u\n", progname); fprintf(stderr, "usage: %s [-nv] [-d ] -R\n", progname); fprintf(stderr, "usage: %s [-nv] [-d ] -W\n", progname); fprintf(stderr, "usage: %s [-nNSv] [-f ] -r\n", progname); fprintf(stderr, "usage: %s [-nNSv] [-f ] -w\n", progname); fprintf(stderr, "usage: %s [-nNSv] -f -i ,\n", progname); exit(1); } /* * Change interface names in state information saved out to disk. */ int changestateif(char *ifs, char *fname) { int fd, olen, nlen, rw; ipstate_save_t ips; off_t pos; char *s; s = strchr(ifs, ','); if (!s) usage(); *s++ = '\0'; nlen = strlen(s); olen = strlen(ifs); if (nlen >= sizeof(ips.ips_is.is_ifname) || olen >= sizeof(ips.ips_is.is_ifname)) usage(); fd = open(fname, O_RDWR); if (fd == -1) { perror("open"); exit(1); } for (pos = 0; read(fd, &ips, sizeof(ips)) == sizeof(ips); ) { rw = 0; if (!strncmp(ips.ips_is.is_ifname[0], ifs, olen + 1)) { strcpy(ips.ips_is.is_ifname[0], s); rw = 1; } if (!strncmp(ips.ips_is.is_ifname[1], ifs, olen + 1)) { strcpy(ips.ips_is.is_ifname[1], s); rw = 1; } if (!strncmp(ips.ips_is.is_ifname[2], ifs, olen + 1)) { strcpy(ips.ips_is.is_ifname[2], s); rw = 1; } if (!strncmp(ips.ips_is.is_ifname[3], ifs, olen + 1)) { strcpy(ips.ips_is.is_ifname[3], s); rw = 1; } if (rw == 1) { if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); exit(1); } if (write(fd, &ips, sizeof(ips)) != sizeof(ips)) { perror("write"); exit(1); } } pos = lseek(fd, 0, SEEK_CUR); } close(fd); - return 0; + return(0); } /* * Change interface names in NAT information saved out to disk. */ int changenatif(char *ifs, char *fname) { int fd, olen, nlen, rw; nat_save_t ipn; nat_t *nat; off_t pos; char *s; s = strchr(ifs, ','); if (!s) usage(); *s++ = '\0'; nlen = strlen(s); olen = strlen(ifs); nat = &ipn.ipn_nat; if (nlen >= sizeof(nat->nat_ifnames[0]) || olen >= sizeof(nat->nat_ifnames[0])) usage(); fd = open(fname, O_RDWR); if (fd == -1) { perror("open"); exit(1); } for (pos = 0; read(fd, &ipn, sizeof(ipn)) == sizeof(ipn); ) { rw = 0; if (!strncmp(nat->nat_ifnames[0], ifs, olen + 1)) { strcpy(nat->nat_ifnames[0], s); rw = 1; } if (!strncmp(nat->nat_ifnames[1], ifs, olen + 1)) { strcpy(nat->nat_ifnames[1], s); rw = 1; } if (rw == 1) { if (lseek(fd, pos, SEEK_SET) != pos) { perror("lseek"); exit(1); } if (write(fd, &ipn, sizeof(ipn)) != sizeof(ipn)) { perror("write"); exit(1); } } pos = lseek(fd, 0, SEEK_CUR); } close(fd); - return 0; + return(0); } int main(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; progname = argv[0]; while ((c = getopt(argc, argv, "d:f:i:lNnSRruvWw")) != -1) switch (c) { case 'd' : if ((set == 0) && !dirname && !filename) dirname = optarg; else usage(); break; case 'f' : if ((set != 0) && !dirname && !filename) filename = optarg; else usage(); break; case 'i' : ifs = optarg; set = 1; break; case 'l' : if (filename || dirname || set) usage(); lock = 1; set = 1; break; case 'n' : opts |= OPT_DONOTHING; break; case 'N' : if ((ns >= 0) || dirname || (rw != -1) || set) usage(); ns = 0; set = 1; break; case 'r' : if (dirname || (rw != -1) || (ns == -1)) usage(); rw = 0; set = 1; break; case 'R' : rw = 2; set = 1; break; case 'S' : if ((ns >= 0) || dirname || (rw != -1) || set) usage(); ns = 1; set = 1; break; case 'u' : if (filename || dirname || set) usage(); lock = 0; set = 1; break; case 'v' : opts |= OPT_VERBOSE; break; case 'w' : if (dirname || (rw != -1) || (ns == -1)) usage(); rw = 1; set = 1; break; case 'W' : rw = 3; set = 1; break; case '?' : default : usage(); } if (ifs) { if (!filename || ns < 0) usage(); if (ns == 0) - return changenatif(ifs, filename); + return(changenatif(ifs, filename)); else - return changestateif(ifs, filename); + return(changestateif(ifs, filename)); } if ((ns >= 0) || (lock >= 0)) { if (lock >= 0) devfd = opendevice(NULL); else if (ns >= 0) { if (ns == 1) devfd = opendevice(IPSTATE_NAME); else if (ns == 0) devfd = opendevice(IPNAT_NAME); } if (devfd == -1) exit(1); } if (lock >= 0) err = setlock(devfd, lock); else if (rw >= 0) { if (rw & 1) { /* WRITE */ if (rw & 2) err = writeall(dirname); else { if (ns == 0) err = writenat(devfd, filename); else if (ns == 1) err = writestate(devfd, filename); } } else { if (rw & 2) err = readall(dirname); else { if (ns == 0) err = readnat(devfd, filename); else if (ns == 1) err = readstate(devfd, filename); } } } - return err; + return(err); } int opendevice(char *ipfdev) { int fd = -1; if (opts & OPT_DONOTHING) - return -2; + return(-2); if (!ipfdev) ipfdev = IPL_NAME; if ((fd = open(ipfdev, O_RDWR)) == -1) if ((fd = open(ipfdev, O_RDONLY)) == -1) perror("open device"); - return fd; + return(fd); } void closedevice(int fd) { close(fd); } int setlock(int fd, int lock) { if (opts & OPT_VERBOSE) printf("Turn lock %s\n", lock ? "on" : "off"); if (!(opts & OPT_DONOTHING)) { if (ioctl(fd, SIOCSTLCK, &lock) == -1) { perror("SIOCSTLCK"); - return 1; + return(1); } if (opts & OPT_VERBOSE) printf("Lock now %s\n", lock ? "on" : "off"); } - return 0; + return(0); } int writestate(int fd, char *file) { ipstate_save_t ips, *ipsp; ipfobj_t obj; int wfd = -1; if (!file) file = IPF_STATEFILE; wfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); if (wfd == -1) { fprintf(stderr, "%s ", file); perror("state:open"); - return 1; + return(1); } ipsp = &ips; bzero((char *)&obj, sizeof(obj)); bzero((char *)ipsp, sizeof(ips)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = sizeof(*ipsp); obj.ipfo_type = IPFOBJ_STATESAVE; obj.ipfo_ptr = ipsp; do { if (opts & OPT_VERBOSE) printf("Getting state from addr %p\n", ips.ips_next); if (ioctl(fd, SIOCSTGET, &obj)) { if (errno == ENOENT) break; perror("state:SIOCSTGET"); close(wfd); - return 1; + return(1); } if (opts & OPT_VERBOSE) printf("Got state next %p\n", ips.ips_next); if (write(wfd, ipsp, sizeof(ips)) != sizeof(ips)) { perror("state:write"); close(wfd); - return 1; + return(1); } } while (ips.ips_next != NULL); close(wfd); - return 0; + return(0); } int readstate(int fd, char *file) { ipstate_save_t ips, *is, *ipshead = NULL, *is1, *ipstail = NULL; int sfd = -1, i; ipfobj_t obj; if (!file) file = IPF_STATEFILE; sfd = open(file, O_RDONLY, 0600); if (sfd == -1) { fprintf(stderr, "%s ", file); perror("open"); - return 1; + return(1); } bzero((char *)&ips, sizeof(ips)); /* * 1. Read all state information in. */ do { i = read(sfd, &ips, sizeof(ips)); if (i == -1) { perror("read"); goto freeipshead; } if (i == 0) break; if (i != sizeof(ips)) { fprintf(stderr, "state:incomplete read: %d != %d\n", i, (int)sizeof(ips)); goto freeipshead; } is = (ipstate_save_t *)malloc(sizeof(*is)); if (is == NULL) { fprintf(stderr, "malloc failed\n"); goto freeipshead; } bcopy((char *)&ips, (char *)is, sizeof(ips)); /* * Check to see if this is the first state entry that will * reference a particular rule and if so, flag it as such * else just adjust the rule pointer to become a pointer to * the other. We do this so we have a means later for tracking * who is referencing us when we get back the real pointer * in is_rule after doing the ioctl. */ for (is1 = ipshead; is1 != NULL; is1 = is1->ips_next) if (is1->ips_rule == is->ips_rule) break; if (is1 == NULL) is->ips_is.is_flags |= SI_NEWFR; else is->ips_rule = (void *)&is1->ips_rule; /* * Use a tail-queue type list (add things to the end).. */ is->ips_next = NULL; if (!ipshead) ipshead = is; if (ipstail) ipstail->ips_next = is; ipstail = is; } while (1); close(sfd); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = sizeof(*is); obj.ipfo_type = IPFOBJ_STATESAVE; while ((is = ipshead) != NULL) { if (opts & OPT_VERBOSE) printf("Loading new state table entry\n"); if (is->ips_is.is_flags & SI_NEWFR) { if (opts & OPT_VERBOSE) printf("Loading new filter rule\n"); } obj.ipfo_ptr = is; if (!(opts & OPT_DONOTHING)) if (ioctl(fd, SIOCSTPUT, &obj)) { perror("SIOCSTPUT"); goto freeipshead; } if (is->ips_is.is_flags & SI_NEWFR) { if (opts & OPT_VERBOSE) printf("Real rule addr %p\n", is->ips_rule); for (is1 = is->ips_next; is1; is1 = is1->ips_next) if (is1->ips_rule == (frentry_t *)&is->ips_rule) is1->ips_rule = is->ips_rule; } ipshead = is->ips_next; free(is); } - return 0; + return(0); freeipshead: while ((is = ipshead) != NULL) { ipshead = is->ips_next; free(is); } if (sfd != -1) close(sfd); - return 1; + return(1); } int readnat(int fd, char *file) { nat_save_t ipn, *in, *ipnhead = NULL, *in1, *ipntail = NULL; ipfobj_t obj; int nfd, i; nat_t *nat; char *s; int n; nfd = -1; in = NULL; ipnhead = NULL; ipntail = NULL; if (!file) file = IPF_NATFILE; nfd = open(file, O_RDONLY); if (nfd == -1) { fprintf(stderr, "%s ", file); perror("nat:open"); - return 1; + return(1); } bzero((char *)&ipn, sizeof(ipn)); /* * 1. Read all state information in. */ do { i = read(nfd, &ipn, sizeof(ipn)); if (i == -1) { perror("read"); goto freenathead; } if (i == 0) break; if (i != sizeof(ipn)) { fprintf(stderr, "nat:incomplete read: %d != %d\n", i, (int)sizeof(ipn)); goto freenathead; } in = (nat_save_t *)malloc(ipn.ipn_dsize); if (in == NULL) { fprintf(stderr, "nat:cannot malloc nat save atruct\n"); goto freenathead; } if (ipn.ipn_dsize > sizeof(ipn)) { n = ipn.ipn_dsize - sizeof(ipn); if (n > 0) { s = in->ipn_data + sizeof(in->ipn_data); i = read(nfd, s, n); if (i == 0) break; if (i != n) { fprintf(stderr, "nat:incomplete read: %d != %d\n", i, n); goto freenathead; } } } bcopy((char *)&ipn, (char *)in, sizeof(ipn)); /* * Check to see if this is the first NAT entry that will * reference a particular rule and if so, flag it as such * else just adjust the rule pointer to become a pointer to * the other. We do this so we have a means later for tracking * who is referencing us when we get back the real pointer * in is_rule after doing the ioctl. */ nat = &in->ipn_nat; if (nat->nat_fr != NULL) { for (in1 = ipnhead; in1 != NULL; in1 = in1->ipn_next) if (in1->ipn_rule == nat->nat_fr) break; if (in1 == NULL) nat->nat_flags |= SI_NEWFR; else nat->nat_fr = &in1->ipn_fr; } /* * Use a tail-queue type list (add things to the end).. */ in->ipn_next = NULL; if (!ipnhead) ipnhead = in; if (ipntail) ipntail->ipn_next = in; ipntail = in; } while (1); close(nfd); nfd = -1; obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_NATSAVE; while ((in = ipnhead) != NULL) { if (opts & OPT_VERBOSE) printf("Loading new NAT table entry\n"); nat = &in->ipn_nat; if (nat->nat_flags & SI_NEWFR) { if (opts & OPT_VERBOSE) printf("Loading new filter rule\n"); } obj.ipfo_ptr = in; obj.ipfo_size = in->ipn_dsize; if (!(opts & OPT_DONOTHING)) if (ioctl(fd, SIOCSTPUT, &obj)) { fprintf(stderr, "in=%p:", in); perror("SIOCSTPUT"); - return 1; + return(1); } if (nat->nat_flags & SI_NEWFR) { if (opts & OPT_VERBOSE) printf("Real rule addr %p\n", nat->nat_fr); for (in1 = in->ipn_next; in1; in1 = in1->ipn_next) if (in1->ipn_rule == &in->ipn_fr) in1->ipn_rule = nat->nat_fr; } ipnhead = in->ipn_next; free(in); } - return 0; + return(0); freenathead: while ((in = ipnhead) != NULL) { ipnhead = in->ipn_next; free(in); } if (nfd != -1) close(nfd); - return 1; + return(1); } int writenat(int fd, char *file) { nat_save_t *ipnp = NULL, *next = NULL; ipfobj_t obj; int nfd = -1; natget_t ng; if (!file) file = IPF_NATFILE; nfd = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); if (nfd == -1) { fprintf(stderr, "%s ", file); perror("nat:open"); - return 1; + return(1); } obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_NATSAVE; do { if (opts & OPT_VERBOSE) printf("Getting nat from addr %p\n", ipnp); ng.ng_ptr = next; ng.ng_sz = 0; if (ioctl(fd, SIOCSTGSZ, &ng)) { perror("nat:SIOCSTGSZ"); close(nfd); if (ipnp != NULL) free(ipnp); - return 1; + return(1); } if (opts & OPT_VERBOSE) printf("NAT size %d from %p\n", ng.ng_sz, ng.ng_ptr); if (ng.ng_sz == 0) break; if (!ipnp) ipnp = malloc(ng.ng_sz); else ipnp = realloc((char *)ipnp, ng.ng_sz); if (!ipnp) { fprintf(stderr, "malloc for %d bytes failed\n", ng.ng_sz); break; } bzero((char *)ipnp, ng.ng_sz); obj.ipfo_size = ng.ng_sz; obj.ipfo_ptr = ipnp; ipnp->ipn_dsize = ng.ng_sz; ipnp->ipn_next = next; if (ioctl(fd, SIOCSTGET, &obj)) { if (errno == ENOENT) break; perror("nat:SIOCSTGET"); close(nfd); free(ipnp); - return 1; + return(1); } if (opts & OPT_VERBOSE) printf("Got nat next %p ipn_dsize %d ng_sz %d\n", ipnp->ipn_next, ipnp->ipn_dsize, ng.ng_sz); if (write(nfd, ipnp, ipnp->ipn_dsize) != ipnp->ipn_dsize) { perror("nat:write"); close(nfd); free(ipnp); - return 1; + return(1); } next = ipnp->ipn_next; } while (ipnp && next); if (ipnp != NULL) free(ipnp); close(nfd); - return 0; + return(0); } int writeall(char *dirname) { int fd, devfd; if (!dirname) dirname = IPF_SAVEDIR; if (chdir(dirname)) { fprintf(stderr, "IPF_SAVEDIR=%s: ", dirname); perror("chdir(IPF_SAVEDIR)"); - return 1; + return(1); } fd = opendevice(NULL); if (fd == -1) - return 1; + return(1); if (setlock(fd, 1)) { close(fd); - return 1; + return(1); } devfd = opendevice(IPSTATE_NAME); if (devfd == -1) goto bad; if (writestate(devfd, NULL)) goto bad; close(devfd); devfd = opendevice(IPNAT_NAME); if (devfd == -1) goto bad; if (writenat(devfd, NULL)) goto bad; close(devfd); if (setlock(fd, 0)) { close(fd); - return 1; + return(1); } close(fd); - return 0; + return(0); bad: setlock(fd, 0); close(fd); - return 1; + return(1); } int readall(char *dirname) { int fd, devfd; if (!dirname) dirname = IPF_SAVEDIR; if (chdir(dirname)) { perror("chdir(IPF_SAVEDIR)"); - return 1; + return(1); } fd = opendevice(NULL); if (fd == -1) - return 1; + return(1); if (setlock(fd, 1)) { close(fd); - return 1; + return(1); } devfd = opendevice(IPSTATE_NAME); if (devfd == -1) - return 1; + return(1); if (readstate(devfd, NULL)) - return 1; + return(1); close(devfd); devfd = opendevice(IPNAT_NAME); if (devfd == -1) - return 1; + return(1); if (readnat(devfd, NULL)) - return 1; + return(1); close(devfd); if (setlock(fd, 0)) { close(fd); - return 1; + return(1); } - return 0; + return(0); } diff --git a/sbin/ipf/ipfstat/ipfstat.c b/sbin/ipf/ipfstat/ipfstat.c index 93345a79e007..a6d782c4f7c9 100644 --- a/sbin/ipf/ipfstat/ipfstat.c +++ b/sbin/ipf/ipfstat/ipfstat.c @@ -1,2316 +1,2316 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include #include # include #include #if defined(sun) && defined(__SVR4) # include #endif #include "ipf.h" #include "netinet/ipl.h" #if defined(STATETOP) # if defined(sun) && defined(__SVR4) # include # endif # include # include # include # include # include # if SOLARIS || defined(__NetBSD__) # ifdef ERR # undef ERR # endif # include # else /* SOLARIS */ # include # endif /* SOLARIS */ #endif /* STATETOP */ #include "kmem.h" #if defined(__NetBSD__) # include #endif #if !defined(lint) static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; extern int optind; extern int opterr; #define PRINTF (void)printf #define FPRINTF (void)fprintf 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; #ifdef USE_INET6 int use_inet4 = 0; int use_inet6 = 0; #endif int live_kernel = 1; int state_fd = -1; int ipf_fd = -1; int auth_fd = -1; 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 #define HOSTNMLEN 40 #define STSORT_PR 0 #define STSORT_PKTS 1 #define STSORT_BYTES 2 #define STSORT_TTL 3 #define STSORT_SRCIP 4 #define STSORT_SRCPT 5 #define STSORT_DSTIP 6 #define STSORT_DSTPT 7 #define STSORT_MAX STSORT_DSTPT #define STSORT_DEFAULT STSORT_BYTES typedef struct statetop { i6addr_t st_src; i6addr_t st_dst; u_short st_sport; u_short st_dport; u_char st_p; u_char st_v; u_char st_state[2]; U_QUAD_T st_pkts; U_QUAD_T st_bytes; u_long st_age; } statetop_t; #endif int main(int, char *[]); static int fetchfrag(int, int, ipfr_t *); static void showstats(friostat_t *, u_32_t); static void showfrstates(ipfrstat_t *, u_long); static void showlist(friostat_t *); static void showstatestats(ips_stat_t *); static void showipstates(ips_stat_t *, int *); static void showauthstates(ipf_authstat_t *); static void showtqtable_live(int); static void showgroups(friostat_t *); static void usage(char *); static int state_matcharray(ipstate_t *, int *); static int printlivelist(friostat_t *, int, int, frentry_t *, char *, char *); static void printdeadlist(friostat_t *, int, int, frentry_t *, char *, char *); static void printside(char *, ipf_statistics_t *); static void parse_ipportstr(const char *, i6addr_t *, int *); static void ipfstate_live(char *, friostat_t **, ips_stat_t **, ipfrstat_t **, ipf_authstat_t **, u_32_t *); static void ipfstate_dead(char *, friostat_t **, ips_stat_t **, ipfrstat_t **, ipf_authstat_t **, u_32_t *); static ipstate_t *fetchstate(ipstate_t *, ipstate_t *); #ifdef STATETOP static void topipstates(i6addr_t, i6addr_t, int, int, int, int, int, int, int *); static void sig_break(int); static void sig_resize(int); static char *getip(int, i6addr_t *); static char *ttl_to_string(long); static int sort_p(const void *, const void *); static int sort_pkts(const void *, const void *); static int sort_bytes(const void *, const void *); static int sort_ttl(const void *, const void *); static int sort_srcip(const void *, const void *); static int sort_srcpt(const void *, const void *); static int sort_dstip(const void *, const void *); static int sort_dstpt(const void *, const void *); #endif static void usage(name) char *name; { #ifdef USE_INET6 fprintf(stderr, "Usage: %s [-46aAdfghIilnoRsv]\n", name); #else fprintf(stderr, "Usage: %s [-4aAdfghIilnoRsv]\n", name); #endif fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); #ifdef STATETOP #ifdef USE_INET6 fprintf(stderr, " %s -t [-46C] ", name); #else fprintf(stderr, " %s -t [-4C] ", name); #endif #endif fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); exit(1); } int main(int argc, char *argv[]) { 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 *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 */ int sport = -1; /* -1 = wild card for any source port */ int dport = -1; /* -1 = wild card for any dest port */ int topclosed = 0; /* do not show closed tcp sessions */ i6addr_t saddr, daddr; u_32_t frf; #ifdef USE_INET6 options = "46aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #else options = "4aACdfghIilnostvD:m:M:N:O:P:RS:T:"; #endif saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ #ifdef USE_INET6 saddr.in6 = in6addr_any; /* default any v6 source addr */ daddr.in6 = in6addr_any; /* default any v6 dest addr */ #endif /* Don't warn about invalid flags when we run getopt for the 1st time */ opterr = 0; /* * Parse these two arguments now lest there be any buffer overflows * in the parsing of the rest. */ myoptind = optind; while ((c = getopt(argc, argv, options)) != -1) { switch (c) { case 'M' : memf = optarg; live_kernel = 0; break; case 'N' : kern = optarg; live_kernel = 0; break; } } optind = myoptind; if (live_kernel == 1) { if ((state_fd = open(IPSTATE_NAME, O_RDONLY)) == -1) { perror("open(IPSTATE_NAME)"); exit(-1); } if ((auth_fd = open(IPAUTH_NAME, O_RDONLY)) == -1) { perror("open(IPAUTH_NAME)"); exit(-1); } if ((nat_fd = open(IPNAT_NAME, O_RDONLY)) == -1) { perror("open(IPAUTH_NAME)"); exit(-1); } if ((ipf_fd = open(IPL_NAME, O_RDONLY)) == -1) { fprintf(stderr, "open(%s)", IPL_NAME); perror(""); exit(-1); } } if (kern != NULL || memf != NULL) { (void)setgid(getgid()); (void)setuid(getuid()); } if (live_kernel == 1) { (void) checkrev(IPL_NAME); } else { if (openkmem(kern, memf) == -1) exit(-1); } (void)setgid(getgid()); (void)setuid(getuid()); opterr = 1; while ((c = getopt(argc, argv, options)) != -1) { switch (c) { #ifdef USE_INET6 case '4' : use_inet4 = 1; break; case '6' : use_inet6 = 1; break; #endif case 'a' : opts |= OPT_ACCNT|OPT_SHOWLIST; break; case 'A' : opts |= OPT_AUTHSTATS; break; case 'C' : topclosed = 1; break; case 'd' : opts |= OPT_DEBUG; break; case 'D' : parse_ipportstr(optarg, &daddr, &dport); break; case 'f' : opts |= OPT_FRSTATES; break; case 'g' : opts |= OPT_GROUPS; break; case 'h' : opts |= OPT_HITS; break; case 'i' : opts |= OPT_INQUE|OPT_SHOWLIST; break; case 'I' : opts |= OPT_INACTIVE; break; 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' : break; case 'n' : opts |= OPT_SHOWLINENO; break; case 'o' : opts |= OPT_OUTQUE|OPT_SHOWLIST; break; case 'O' : state_fields = parsefields(statefields, optarg); break; case 'P' : protocol = getproto(optarg); if (protocol == -1) { fprintf(stderr, "%s: Invalid protocol: %s\n", argv[0], optarg); exit(-2); } break; case 'R' : opts |= OPT_NORESOLVE; break; case 's' : opts |= OPT_IPSTATES; break; case 'S' : parse_ipportstr(optarg, &saddr, &sport); break; case 't' : #ifdef STATETOP opts |= OPT_STATETOP; break; #else fprintf(stderr, "%s: state top facility not compiled in\n", argv[0]); exit(-2); #endif case 'T' : if (!sscanf(optarg, "%d", &refreshtime) || (refreshtime <= 0)) { fprintf(stderr, "%s: Invalid refreshtime < 1 : %s\n", argv[0], optarg); exit(-2); } break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; } } #ifdef USE_INET6 if ((use_inet4 || use_inet6) && !(opts & (OPT_INQUE | OPT_OUTQUE | OPT_STATETOP))) { #ifdef STATETOP FPRINTF(stderr, "No -i, -o, or -t given with -4 or -6\n"); #else FPRINTF(stderr, "No -i or -o given with -4 or -6\n"); #endif exit(-2); } if (use_inet4 == 0 && use_inet6 == 0) use_inet4 = use_inet6 = 1; #endif if (live_kernel == 1) { bzero((char *)&fio, sizeof(fio)); bzero((char *)&ipsst, sizeof(ipsst)); bzero((char *)&ifrst, sizeof(ifrst)); ipfstate_live(IPL_NAME, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); } else { ipfstate_dead(kern, &fiop, &ipsstp, &ifrstp, &frauthstp, &frf); } if (opts & OPT_IPSTATES) { showipstates(ipsstp, filter); } else if (opts & OPT_SHOWLIST) { showlist(fiop); if ((opts & OPT_OUTQUE) && (opts & OPT_INQUE)){ opts &= ~OPT_OUTQUE; showlist(fiop); } } else if (opts & OPT_FRSTATES) showfrstates(ifrstp, fiop->f_ticks); #ifdef STATETOP else if (opts & OPT_STATETOP) topipstates(saddr, daddr, sport, dport, protocol, #ifdef USE_INET6 use_inet6 && use_inet4 ? 0 : use_inet6 && !use_inet4 ? 6 : 4, #else 4, #endif #endif refreshtime, topclosed, filter); else if (opts & OPT_AUTHSTATS) showauthstates(frauthstp); else if (opts & OPT_GROUPS) showgroups(fiop); else showstats(fiop, frf); - return 0; + return(0); } /* * Fill in the stats structures from the live kernel, using a combination * of ioctl's and copying directly from kernel memory. */ static void ipfstate_live(char *device, friostat_t **fiopp, ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp, ipf_authstat_t **frauthstpp, u_32_t *frfp) { ipfobj_t ipfo; if (checkrev(device) == -1) { fprintf(stderr, "User/kernel version check failed\n"); exit(1); } if ((opts & OPT_AUTHSTATS) == 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_IPFSTAT; ipfo.ipfo_size = sizeof(friostat_t); ipfo.ipfo_ptr = (void *)*fiopp; if (ioctl(ipf_fd, SIOCGETFS, &ipfo) == -1) { ipferror(ipf_fd, "ioctl(ipf:SIOCGETFS)"); exit(-1); } if (ioctl(ipf_fd, SIOCGETFF, frfp) == -1) ipferror(ipf_fd, "ioctl(SIOCGETFF)"); } if ((opts & OPT_IPSTATES) != 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_STATESTAT; ipfo.ipfo_size = sizeof(ips_stat_t); ipfo.ipfo_ptr = (void *)*ipsstpp; if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { ipferror(state_fd, "ioctl(state:SIOCGETFS)"); exit(-1); } if (ioctl(state_fd, SIOCGETLG, &state_logging) == -1) { ipferror(state_fd, "ioctl(state:SIOCGETLG)"); exit(-1); } } if ((opts & OPT_FRSTATES) != 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_FRAGSTAT; ipfo.ipfo_size = sizeof(ipfrstat_t); ipfo.ipfo_ptr = (void *)*ifrstpp; if (ioctl(ipf_fd, SIOCGFRST, &ipfo) == -1) { ipferror(ipf_fd, "ioctl(SIOCGFRST)"); exit(-1); } } if (opts & OPT_DEBUG) PRINTF("opts %#x name %s\n", opts, device); if ((opts & OPT_AUTHSTATS) != 0) { bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_AUTHSTAT; ipfo.ipfo_size = sizeof(ipf_authstat_t); ipfo.ipfo_ptr = (void *)*frauthstpp; if (ioctl(auth_fd, SIOCATHST, &ipfo) == -1) { ipferror(auth_fd, "ioctl(SIOCATHST)"); exit(-1); } } } /* * Build up the stats structures from data held in the "core" memory. * This is mainly useful when looking at data in crash dumps and ioctl's * just won't work any more. */ static void ipfstate_dead( char *kernel, friostat_t **fiopp, ips_stat_t **ipsstpp, ipfrstat_t **ifrstpp, ipf_authstat_t **frauthstpp, u_32_t *frfp) { 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; int temp; void *rules[2][2]; struct nlist deadlist[44] = { { "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 } }; frauthstp = &frauthst; ipsstp = &ipsst; ifrstp = &ifrst; fiop = &fio; *frfp = 0; *fiopp = fiop; *ipsstpp = ipsstp; *ifrstpp = ifrstp; *frauthstpp = frauthstp; bzero((char *)fiop, sizeof(*fiop)); bzero((char *)ipsstp, sizeof(*ipsstp)); bzero((char *)ifrstp, sizeof(*ifrstp)); bzero((char *)frauthstp, sizeof(*frauthstp)); if (nlist(kernel, deadlist) == -1) { fprintf(stderr, "nlist error\n"); return; } /* * This is for SIOCGETFF. */ kmemcpy((char *)frfp, (u_long)deadlist[40].n_value, sizeof(*frfp)); /* * f_locks is a combination of the lock variable from each part of * ipfilter (state, auth, nat, fragments). */ kmemcpy((char *)fiop, (u_long)deadlist[13].n_value, sizeof(*fiop)); kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[22].n_value, sizeof(fiop->f_locks[0])); kmemcpy((char *)&fiop->f_locks[0], (u_long)deadlist[30].n_value, sizeof(fiop->f_locks[1])); kmemcpy((char *)&fiop->f_locks[2], (u_long)deadlist[28].n_value, sizeof(fiop->f_locks[2])); kmemcpy((char *)&fiop->f_locks[3], (u_long)deadlist[12].n_value, sizeof(fiop->f_locks[3])); /* * Get pointers to each list of rules (active, inactive, in, out) */ kmemcpy((char *)&rules, (u_long)deadlist[31].n_value, sizeof(rules)); fiop->f_fin[0] = rules[0][0]; fiop->f_fin[1] = rules[0][1]; fiop->f_fout[0] = rules[1][0]; fiop->f_fout[1] = rules[1][1]; /* * Now get accounting rules pointers. */ kmemcpy((char *)&rules, (u_long)deadlist[33].n_value, sizeof(rules)); fiop->f_acctin[0] = rules[0][0]; fiop->f_acctin[1] = rules[0][1]; fiop->f_acctout[0] = rules[1][0]; fiop->f_acctout[1] = rules[1][1]; /* * 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[33].n_value, sizeof(fiop->f_froute)); kmemcpy((char *)&fiop->f_running, (u_long)deadlist[34].n_value, sizeof(fiop->f_running)); kmemcpy((char *)&fiop->f_groups, (u_long)deadlist[35].n_value, sizeof(fiop->f_groups)); kmemcpy((char *)&fiop->f_active, (u_long)deadlist[36].n_value, sizeof(fiop->f_active)); kmemcpy((char *)&fiop->f_defpass, (u_long)deadlist[37].n_value, sizeof(fiop->f_defpass)); /* * Build up the state information stats structure. */ kmemcpy((char *)ipsstp, (u_long)deadlist[14].n_value, sizeof(*ipsstp)); kmemcpy((char *)&temp, (u_long)deadlist[15].n_value, sizeof(temp)); 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 = ipstcptab; /* * Build up the authentiation information stats structure. */ kmemcpy((char *)frauthstp, (u_long)deadlist[0].n_value, sizeof(*frauthstp)); frauthstp->fas_faelist = (void *)deadlist[1].n_value; /* * Build up the fragment information stats structure. */ kmemcpy((char *)ifrstp, (u_long)deadlist[25].n_value, sizeof(*ifrstp)); ifrstp->ifs_table = (void *)deadlist[23].n_value; ifrstp->ifs_nattab = (void *)deadlist[24].n_value; kmemcpy((char *)&ifrstp->ifs_inuse, (u_long)deadlist[26].n_value, sizeof(ifrstp->ifs_inuse)); /* * Get logging on/off switches */ kmemcpy((char *)&state_logging, (u_long)deadlist[41].n_value, sizeof(state_logging)); } static void printside(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( struct friostat *fp, u_32_t frf) { printside("input", &fp->f_st[0]); printside("output", &fp->f_st[1]); 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("%x\tPacket log flags set:\n", frf); if (frf & FF_LOGPASS) PRINTF("\tpackets passed through filter\n"); if (frf & FF_LOGBLOCK) PRINTF("\tpackets blocked by filter\n"); if (frf & FF_LOGNOMATCH) PRINTF("\tpackets not matched by filter\n"); if (!frf) PRINTF("\tnone\n"); } /* * Print out a list of rules from the kernel, starting at the one passed. */ static int printlivelist( struct friostat *fiop, int out, int set, frentry_t *fp, char *group, char *comment) { struct frentry fb; ipfruleiter_t rule; frentry_t zero; frgroup_t *g; ipfobj_t obj; int rules; int num; rules = 0; rule.iri_inout = out; rule.iri_active = set; rule.iri_rule = &fb; rule.iri_nrules = 1; if (group != NULL) strncpy(rule.iri_group, group, FR_GROUPLEN); else rule.iri_group[0] = '\0'; bzero((char *)&zero, sizeof(zero)); bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_IPFITER; obj.ipfo_size = sizeof(rule); obj.ipfo_ptr = &rule; 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) { ipferror(ipf_fd, "ioctl(SIOCIPFITER)"); num = IPFGENITER_IPF; (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); - return rules; + return(rules); } if (bcmp(fp, &zero, sizeof(zero)) == 0) break; if (rule.iri_rule == NULL) break; #ifdef USE_INET6 if (use_inet6 != 0 && use_inet4 == 0) { if (fp->fr_family != 0 && fp->fr_family != AF_INET6) continue; } else if (use_inet4 != 0 && use_inet6 == 0) { #endif if (fp->fr_family != 0 && fp->fr_family != AF_INET) continue; #ifdef USE_INET6 } else { if (fp->fr_family != 0 && fp->fr_family != AF_INET && fp->fr_family != AF_INET6) continue; } #endif if (fp->fr_data != NULL) fp->fr_data = (char *)fp + fp->fr_size; rules++; if (opts & (OPT_HITS|OPT_DEBUG)) #ifdef USE_QUAD_T PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_hits); #else PRINTF("%lu ", fp->fr_hits); #endif if (opts & (OPT_ACCNT|OPT_DEBUG)) #ifdef USE_QUAD_T PRINTF("%"PRIu64" ", (unsigned long long) fp->fr_bytes); #else PRINTF("%lu ", fp->fr_bytes); #endif if (opts & OPT_SHOWLINENO) PRINTF("@%d ", rules); if (fp->fr_die != 0) fp->fr_die -= fiop->f_ticks; printfr(fp, ioctl); if (opts & OPT_DEBUG) { 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 != -1) { for (g = grtop; g != NULL; g = g->fg_next) { if (!strncmp(fp->fr_names + fp->fr_grhead, g->fg_name, FR_GROUPLEN)) break; } if (g == NULL) { g = calloc(1, sizeof(*g)); if (g != NULL) { strncpy(g->fg_name, fp->fr_names + fp->fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; grtail = g; } else { grtail->fg_next = g; grtail = g; } } } } if (fp->fr_type == FR_T_CALLFUNC) { rules += printlivelist(fiop, out, set, fp->fr_data, group, "# callfunc: "); } } num = IPFGENITER_IPF; (void) ioctl(ipf_fd,SIOCIPFDELTOK, &num); - return rules; + return(rules); } static void printdeadlist(friostat_t *fiop, int out, int set, frentry_t *fp, char *group, char *comment) { frgroup_t *grtop, *grtail, *g; struct frentry fb; char *data; u_32_t type; int n; fb.fr_next = fp; n = 0; grtop = NULL; grtail = NULL; for (n = 1; fp; fp = fb.fr_next, n++) { if (kmemcpy((char *)&fb, (u_long)fb.fr_next, fb.fr_size) == -1) { perror("kmemcpy"); return; } fp = &fb; #ifdef USE_INET6 if (use_inet6 != 0 && use_inet4 == 0) { if (fp->fr_family != 0 && fp->fr_family != AF_INET6) continue; } else if (use_inet4 != 0 && use_inet6 == 0) { #endif if (fp->fr_family != 0 && fp->fr_family != AF_INET) continue; #ifdef USE_INET6 } else { if (fp->fr_family != 0 && fp->fr_family != AF_INET && fp->fr_family != AF_INET6) continue; } #endif data = NULL; type = fb.fr_type & ~FR_T_BUILTIN; if (type == FR_T_IPF || type == FR_T_BPFOPC) { if (fb.fr_dsize) { data = malloc(fb.fr_dsize); if (kmemcpy(data, (u_long)fb.fr_data, fb.fr_dsize) == -1) { perror("kmemcpy"); return; } fb.fr_data = data; } } if (opts & OPT_HITS) #ifdef USE_QUAD_T PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_hits); #else PRINTF("%lu ", fb.fr_hits); #endif if (opts & OPT_ACCNT) #ifdef USE_QUAD_T PRINTF("%"PRIu64" ", (unsigned long long) fb.fr_bytes); #else PRINTF("%lu ", fb.fr_bytes); #endif if (opts & OPT_SHOWLINENO) PRINTF("@%d ", n); printfr(fp, ioctl); if (opts & OPT_DEBUG) { 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 != -1) { g = calloc(1, sizeof(*g)); if (g != NULL) { strncpy(g->fg_name, fb.fr_names + fb.fr_grhead, FR_GROUPLEN); if (grtop == NULL) { grtop = g; grtail = g; } else { grtail->fg_next = g; grtail = g; } } } if (type == FR_T_CALLFUNC) { printdeadlist(fiop, out, set, fb.fr_data, group, "# callfunc: "); } } while ((g = grtop) != NULL) { printdeadlist(fiop, out, set, NULL, g->fg_name, comment); grtop = g->fg_next; free(g); } } /* * print out all of the asked for rule sets, using the stats struct as * the base from which to get the pointers. */ static void showlist(struct friostat *fiop) { struct frentry *fp = NULL; int i, set; set = fiop->f_active; if (opts & OPT_INACTIVE) set = 1 - set; if (opts & OPT_ACCNT) { if (opts & OPT_OUTQUE) { i = F_ACOUT; fp = (struct frentry *)fiop->f_acctout[set]; } else if (opts & OPT_INQUE) { i = F_ACIN; fp = (struct frentry *)fiop->f_acctin[set]; } else { FPRINTF(stderr, "No -i or -o given with -a\n"); return; } } else { if (opts & OPT_OUTQUE) { i = F_OUT; fp = (struct frentry *)fiop->f_fout[set]; } else if (opts & OPT_INQUE) { i = F_IN; fp = (struct frentry *)fiop->f_fin[set]; } else return; } if (opts & OPT_DEBUG) FPRINTF(stderr, "showlist:opts %#x i %d\n", opts, i); if (opts & OPT_DEBUG) PRINTF("fp %p set %d\n", fp, set); 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); } } } /* * Display ipfilter stateful filtering information */ static void showipstates(ips_stat_t *ipsp, int *filter) { 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; } 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"); } /* * Print out all the state information currently held in the kernel. */ for (is = ipsp->iss_list; is != NULL; ) { ipstate_t ips; is = fetchstate(is, &ips); 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 { printstate(&ips, opts, ipsp->iss_ticks); } } } static void showstatestats(ips_stat_t *ipsp) { int minlen, maxlen, totallen; ipftable_t table; u_int *buckets; ipfobj_t obj; int i, sz; /* * If a list of states hasn't been asked for, only print out stats */ sz = sizeof(*buckets) * ipsp->iss_state_size; buckets = (u_int *)malloc(sz); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GTABLE; obj.ipfo_size = sizeof(table); obj.ipfo_ptr = &table; table.ita_type = IPFTABLE_BUCKETS; table.ita_table = buckets; if (live_kernel == 1) { if (ioctl(state_fd, SIOCGTABL, &obj) != 0) { free(buckets); return; } } else { if (kmemcpy((char *)buckets, (u_long)ipsp->iss_bucketlen, sz)) { free(buckets); return; } } 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); 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); } } 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]; } 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); #define ENTRIES_PER_LINE 5 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); } } #ifdef STATETOP static int handle_resize = 0, handle_break = 0; static void topipstates(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; ipfobj_t ipfo; struct timeval selecttimeout; char hostnm[HOSTNMLEN]; struct protoent *proto; fd_set readfd; time_t t; /* install signal handlers */ signal(SIGINT, sig_break); signal(SIGQUIT, sig_break); signal(SIGTERM, sig_break); signal(SIGWINCH, sig_resize); /* init ncurses stuff */ initscr(); cbreak(); noecho(); curs_set(0); timeout(0); getmaxyx(stdscr, maxy, maxx); /* init hostname */ gethostname(hostnm, sizeof(hostnm) - 1); hostnm[sizeof(hostnm) - 1] = '\0'; /* init ipfobj_t stuff */ bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; ipfo.ipfo_type = IPFOBJ_STATESTAT; ipfo.ipfo_size = sizeof(*ipsstp); ipfo.ipfo_ptr = (void *)ipsstp; /* repeat until user aborts */ while ( 1 ) { /* get state table */ bzero((char *)&ipsst, sizeof(ipsst)); if ((ioctl(state_fd, SIOCGETFS, &ipfo) == -1)) { errstr = "ioctl(SIOCGETFS)"; ret = -1; goto out; } /* clear the history */ tsentry = -1; /* reset max str len */ srclen = dstlen = 0; /* read the state table and store in tstable */ for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { ipsstp->iss_list = fetchstate(ipsstp->iss_list, &ips); if (ipsstp->iss_list == NULL) break; if (ver != 0 && 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 && saddr.in4.s_addr != ips.is_saddr) || (daddr.in4.s_addr != INADDR_ANY && daddr.in4.s_addr != ips.is_daddr)) continue; } #ifdef USE_INET6 /* check v6 src/dest addresses */ if (ips.is_v == 6) { if ((IP6_NEQ(&saddr, &in6addr_any) && IP6_NEQ(&saddr, &ips.is_src)) || (IP6_NEQ(&daddr, &in6addr_any) && IP6_NEQ(&daddr, &ips.is_dst))) continue; } #endif /* check protocol */ if (protocol > 0 && protocol != ips.is_p) continue; /* check ports if protocol is TCP or UDP */ if (((ips.is_p == IPPROTO_TCP) || (ips.is_p == IPPROTO_UDP)) && (((sport > 0) && (htons(sport) != ips.is_sport)) || ((dport > 0) && (htons(dport) != ips.is_dport)))) continue; /* show closed TCP sessions ? */ if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) continue; /* * if necessary make room for this state * entry */ tsentry++; if (!maxtsentries || tsentry == maxtsentries) { maxtsentries += STGROWSIZE; tstable = reallocarray(tstable, maxtsentries, sizeof(statetop_t)); if (tstable == NULL) { perror("realloc"); exit(-1); } } /* get max src/dest address string length */ len = strlen(getip(ips.is_v, &ips.is_src)); if (srclen < len) srclen = len; len = strlen(getip(ips.is_v, &ips.is_dst)); if (dstlen < len) dstlen = len; /* fill structure */ tp = tstable + tsentry; tp->st_src = ips.is_src; tp->st_dst = ips.is_dst; tp->st_p = ips.is_p; tp->st_v = ips.is_v; tp->st_state[0] = ips.is_state[0]; tp->st_state[1] = ips.is_state[1]; if (forward) { tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; } else { tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; } tp->st_age = ips.is_die - ipsstp->iss_ticks; if ((ips.is_p == IPPROTO_TCP) || (ips.is_p == IPPROTO_UDP)) { tp->st_sport = ips.is_sport; tp->st_dport = ips.is_dport; } } (void) ioctl(state_fd, SIOCIPFDELTOK, &token_type); /* sort the array */ if (tsentry != -1) { switch (sorting) { case STSORT_PR: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_p); break; case STSORT_PKTS: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_pkts); break; case STSORT_BYTES: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_bytes); break; case STSORT_TTL: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_ttl); break; case STSORT_SRCIP: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_srcip); break; case STSORT_SRCPT: qsort(tstable, tsentry +1, sizeof(statetop_t), sort_srcpt); break; case STSORT_DSTIP: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_dstip); break; case STSORT_DSTPT: qsort(tstable, tsentry + 1, sizeof(statetop_t), sort_dstpt); break; default: break; } } /* handle window resizes */ if (handle_resize) { endwin(); initscr(); cbreak(); noecho(); curs_set(0); timeout(0); getmaxyx(stdscr, maxy, maxx); redraw = 1; handle_resize = 0; } /* stop program? */ if (handle_break) break; /* print title */ erase(); attron(A_BOLD); winy = 0; move(winy,0); snprintf(str1, sizeof(str1), "%s - %s - state top", hostnm, IPL_VERSION); for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) printw(" "); printw("%s", str1); attroff(A_BOLD); /* just for fun add a clock */ move(winy, maxx - 8); t = time(NULL); strftime(str1, 80, "%T", localtime(&t)); printw("%s\n", str1); /* * print the display filters, this is placed in the loop, * because someday I might add code for changing these * while the programming is running :-) */ if (sport >= 0) snprintf(str1, sizeof(str1), "%s,%d", getip(ver, &saddr), sport); else snprintf(str1, sizeof(str1), "%s", getip(ver, &saddr)); if (dport >= 0) snprintf(str2, sizeof(str2), "%s,%d", getip(ver, &daddr), dport); else snprintf(str2, sizeof(str2), "%s", getip(ver, &daddr)); if (protocol < 0) strcpy(str3, "any"); else if ((proto = getprotobynumber(protocol)) != NULL) snprintf(str3, sizeof(str3), "%s", proto->p_name); else snprintf(str3, sizeof(str3), "%d", protocol); switch (sorting) { case STSORT_PR: snprintf(str4, sizeof(str4), "proto"); break; case STSORT_PKTS: snprintf(str4, sizeof(str4), "# pkts"); break; case STSORT_BYTES: snprintf(str4, sizeof(str4), "# bytes"); break; case STSORT_TTL: snprintf(str4, sizeof(str4), "ttl"); break; case STSORT_SRCIP: snprintf(str4, sizeof(str4), "src ip"); break; case STSORT_SRCPT: snprintf(str4, sizeof(str4), "src port"); break; case STSORT_DSTIP: snprintf(str4, sizeof(str4), "dest ip"); break; case STSORT_DSTPT: snprintf(str4, sizeof(str4), "dest port"); break; default: snprintf(str4, sizeof(str4), "unknown"); break; } if (reverse) strcat(str4, " (reverse)"); winy += 2; move(winy,0); 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. * We are lacking a good solution for IPv6 addresses (that * can be longer that 15 characters), so we do not enforce * a maximum on the IP field size. */ if (srclen < 15) srclen = 15; if (dstlen < 15) dstlen = 15; /* print column description */ winy += 2; move(winy,0); attron(A_BOLD); printw("%-*s %-*s %3s %4s %7s %9s %9s\n", srclen + 6, "Source IP", dstlen + 6, "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); attroff(A_BOLD); /* print all the entries */ tp = tstable; if (reverse) tp += tsentry; if (tsentry > maxy - 6) tsentry = maxy - 6; for (i = 0; i <= tsentry; i++) { /* print src/dest and port */ if ((tp->st_p == IPPROTO_TCP) || (tp->st_p == IPPROTO_UDP)) { snprintf(str1, sizeof(str1), "%s,%hu", getip(tp->st_v, &tp->st_src), ntohs(tp->st_sport)); snprintf(str2, sizeof(str2), "%s,%hu", getip(tp->st_v, &tp->st_dst), ntohs(tp->st_dport)); } else { snprintf(str1, sizeof(str1), "%s", getip(tp->st_v, &tp->st_src)); snprintf(str2, sizeof(str2), "%s", getip(tp->st_v, &tp->st_dst)); } winy++; move(winy, 0); printw("%-*s %-*s", srclen + 6, str1, dstlen + 6, str2); /* print state */ snprintf(str1, sizeof(str1), "%X/%X", tp->st_state[0], tp->st_state[1]); printw(" %3s", str1); /* print protocol */ proto = getprotobynumber(tp->st_p); if (proto) { strncpy(str1, proto->p_name, 4); str1[4] = '\0'; } else { snprintf(str1, sizeof(str1), "%d", tp->st_p); } /* just print icmp for IPv6-ICMP */ if (tp->st_p == IPPROTO_ICMPV6) strcpy(str1, "icmp"); printw(" %4s", str1); /* print #pkt/#bytes */ #ifdef USE_QUAD_T printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, (unsigned long long) tp->st_bytes); #else printw(" %7lu %9lu", tp->st_pkts, tp->st_bytes); #endif printw(" %9s", ttl_to_string(tp->st_age)); if (reverse) tp--; else tp++; } /* screen data structure is filled, now update the screen */ if (redraw) clearok(stdscr,1); if (refresh() == ERR) break; if (redraw) { clearok(stdscr,0); redraw = 0; } /* wait for key press or a 1 second time out period */ selecttimeout.tv_sec = refreshtime; selecttimeout.tv_usec = 0; FD_ZERO(&readfd); FD_SET(0, &readfd); select(1, &readfd, NULL, NULL, &selecttimeout); /* if key pressed, read all waiting keys */ if (FD_ISSET(0, &readfd)) { c = wgetch(stdscr); if (c == ERR) continue; if (ISALPHA(c) && ISUPPER(c)) c = TOLOWER(c); if (c == 'l') { redraw = 1; } else if (c == 'q') { break; } else if (c == 'r') { reverse = !reverse; } else if (c == 'b') { forward = 0; } else if (c == 'f') { forward = 1; } else if (c == 's') { if (++sorting > STSORT_MAX) sorting = 0; } } } /* while */ out: printw("\n"); curs_set(1); /* nocbreak(); XXX - endwin() should make this redundant */ endwin(); free(tstable); if (ret != 0) perror(errstr); } #endif /* * Show fragment cache information that's held in the kernel. */ static void showfrstates(ipfrstat_t *ifsp, u_long ticks) { struct ipfr *ipfrtab[IPFT_SIZE], ifr; int i; /* * print out the numeric statistics */ PRINTF("IP fragment states:\n%lu\tnew\n%lu\texpired\n%lu\thits\n", ifsp->ifs_new, ifsp->ifs_expire, ifsp->ifs_hits); PRINTF("%lu\tretrans\n%lu\ttoo short\n", ifsp->ifs_retrans0, ifsp->ifs_short); PRINTF("%lu\tno memory\n%lu\talready exist\n", ifsp->ifs_nomem, ifsp->ifs_exists); PRINTF("%lu\tinuse\n", ifsp->ifs_inuse); PRINTF("\n"); if (live_kernel == 0) { if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_table, sizeof(ipfrtab))) return; } /* * Print out the contents (if any) of the fragment cache table. */ if (live_kernel == 1) { do { if (fetchfrag(ipf_fd, IPFGENITER_FRAG, &ifr) != 0) break; if (ifr.ipfr_ifp == NULL) break; ifr.ipfr_ttl -= ticks; printfraginfo("", &ifr); } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], sizeof(ifr)) == -1) break; printfraginfo("", &ifr); ipfrtab[i] = ifr.ipfr_next; } } /* * Print out the contents (if any) of the NAT fragment cache table. */ if (live_kernel == 0) { if (kmemcpy((char *)ipfrtab, (u_long)ifsp->ifs_nattab, sizeof(ipfrtab))) return; } if (live_kernel == 1) { do { if (fetchfrag(nat_fd, IPFGENITER_NATFRAG, &ifr) != 0) break; if (ifr.ipfr_ifp == NULL) break; ifr.ipfr_ttl -= ticks; printfraginfo("NAT: ", &ifr); } while (ifr.ipfr_next != NULL); } else { for (i = 0; i < IPFT_SIZE; i++) while (ipfrtab[i] != NULL) { if (kmemcpy((char *)&ifr, (u_long)ipfrtab[i], sizeof(ifr)) == -1) break; printfraginfo("NAT: ", &ifr); ipfrtab[i] = ifr.ipfr_next; } } } /* * Show stats on how auth within IPFilter has been used */ static void showauthstates(ipf_authstat_t *asp) { frauthent_t *frap, fra; ipfgeniter_t auth; ipfobj_t obj; obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GENITER; obj.ipfo_size = sizeof(auth); obj.ipfo_ptr = &auth; auth.igi_type = IPFGENITER_AUTH; auth.igi_nitems = 1; auth.igi_data = &fra; #ifdef USE_QUAD_T printf("Authorisation hits: %"PRIu64"\tmisses %"PRIu64"\n", (unsigned long long) asp->fas_hits, (unsigned long long) asp->fas_miss); #else printf("Authorisation hits: %ld\tmisses %ld\n", asp->fas_hits, asp->fas_miss); #endif printf("nospace %ld\nadded %ld\nsendfail %ld\nsendok %ld\n", asp->fas_nospace, asp->fas_added, asp->fas_sendfail, asp->fas_sendok); printf("queok %ld\nquefail %ld\nexpire %ld\n", asp->fas_queok, asp->fas_quefail, asp->fas_expire); frap = asp->fas_faelist; while (frap) { if (live_kernel == 1) { if (ioctl(auth_fd, SIOCGENITER, &obj)) break; } else { if (kmemcpy((char *)&fra, (u_long)frap, sizeof(fra)) == -1) break; } printf("age %ld\t", fra.fae_age); printfr(&fra.fae_fr, ioctl); frap = fra.fae_next; } } /* * Display groups used for each of filter rules, accounting rules and * authentication, separately. */ static void showgroups(struct friostat *fiop) { static char *gnames[3] = { "Filter", "Accounting", "Authentication" }; static int gnums[3] = { IPL_LOGIPF, IPL_LOGCOUNT, IPL_LOGAUTH }; frgroup_t *fp, grp; int on, off, i; on = fiop->f_active; off = 1 - on; for (i = 0; i < 3; i++) { printf("%s groups (active):\n", gnames[i]); for (fp = fiop->f_groups[gnums[i]][on]; fp != NULL; fp = grp.fg_next) if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) break; else printf("%s\n", grp.fg_name); printf("%s groups (inactive):\n", gnames[i]); for (fp = fiop->f_groups[gnums[i]][off]; fp != NULL; fp = grp.fg_next) if (kmemcpy((char *)&grp, (u_long)fp, sizeof(grp))) break; else printf("%s\n", grp.fg_name); } } static void parse_ipportstr(const char *argument, i6addr_t *ip, int *port) { char *s, *comma; int ok = 0; /* make working copy of argument, Theoretically you must be able * to write to optarg, but that seems very ugly to me.... */ s = strdup(argument); if (s == NULL) return; /* get port */ if ((comma = strchr(s, ',')) != NULL) { if (!strcasecmp(comma + 1, "any")) { *port = -1; } else if (!sscanf(comma + 1, "%d", port) || (*port < 0) || (*port > 65535)) { fprintf(stderr, "Invalid port specification in %s\n", argument); free(s); exit(-2); } *comma = '\0'; } /* get ip address */ if (!strcasecmp(s, "any")) { ip->in4.s_addr = INADDR_ANY; ok = 1; #ifdef USE_INET6 ip->in6 = in6addr_any; } else if (use_inet6 && !use_inet4 && inet_pton(AF_INET6, s, &ip->in6)) { ok = 1; #endif } else if (inet_aton(s, &ip->in4)) ok = 1; if (ok == 0) { fprintf(stderr, "Invalid IP address: %s\n", s); free(s); exit(-2); } /* free allocated memory */ free(s); } #ifdef STATETOP static void sig_resize(int s) { handle_resize = 1; } static void sig_break(int s) { handle_break = 1; } static char *getip(int v, i6addr_t *addr) { #ifdef USE_INET6 static char hostbuf[MAXHOSTNAMELEN+1]; #endif if (v == 0) - return ("any"); + return("any"); if (v == 4) - return inet_ntoa(addr->in4); + return(inet_ntoa(addr->in4)); #ifdef USE_INET6 (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); hostbuf[MAXHOSTNAMELEN] = '\0'; - return hostbuf; + return(hostbuf); #else - return "IPv6"; + return("IPv6"); #endif } static char *ttl_to_string(long int ttl) { static char ttlbuf[STSTRSIZE]; int hours, minutes, seconds; /* ttl is in half seconds */ ttl /= 2; hours = ttl / 3600; ttl = ttl % 3600; minutes = ttl / 60; seconds = ttl % 60; if (hours > 0) snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d:%02d", hours, minutes, seconds); else snprintf(ttlbuf, sizeof(ttlbuf), "%2d:%02d", minutes, seconds); - return ttlbuf; + return(ttlbuf); } static int sort_pkts(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (ap->st_pkts == bp->st_pkts) - return 0; + return(0); else if (ap->st_pkts < bp->st_pkts) - return 1; - return -1; + return(1); + return(-1); } static int sort_bytes(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (ap->st_bytes == bp->st_bytes) - return 0; + return(0); else if (ap->st_bytes < bp->st_bytes) - return 1; - return -1; + return(1); + return(-1); } static int sort_p(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (ap->st_p == bp->st_p) - return 0; + return(0); else if (ap->st_p < bp->st_p) - return 1; - return -1; + return(1); + return(-1); } static int sort_ttl(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (ap->st_age == bp->st_age) - return 0; + return(0); else if (ap->st_age < bp->st_age) - return 1; - return -1; + return(1); + return(-1); } static int sort_srcip(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; #ifdef USE_INET6 if (use_inet6 && !use_inet4) { if (IP6_EQ(&ap->st_src, &bp->st_src)) - return 0; + return(0); else if (IP6_GT(&ap->st_src, &bp->st_src)) - return 1; + return(1); } else #endif { if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) - return 0; + return(0); else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) - return 1; + return(1); } - return -1; + return(-1); } static int sort_srcpt(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (htons(ap->st_sport) == htons(bp->st_sport)) - return 0; + return(0); else if (htons(ap->st_sport) > htons(bp->st_sport)) - return 1; - return -1; + return(1); + return(-1); } static int sort_dstip(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; #ifdef USE_INET6 if (use_inet6 && !use_inet4) { if (IP6_EQ(&ap->st_dst, &bp->st_dst)) - return 0; + return(0); else if (IP6_GT(&ap->st_dst, &bp->st_dst)) - return 1; + return(1); } else #endif { if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) - return 0; + return(0); else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) - return 1; + return(1); } - return -1; + return(-1); } static int sort_dstpt(const void *a, const void *b) { register const statetop_t *ap = a; register const statetop_t *bp = b; if (htons(ap->st_dport) == htons(bp->st_dport)) - return 0; + return(0); else if (htons(ap->st_dport) > htons(bp->st_dport)) - return 1; - return -1; + return(1); + return(-1); } #endif ipstate_t *fetchstate(ipstate_t *src, ipstate_t *dst) { if (live_kernel == 1) { ipfgeniter_t state; ipfobj_t obj; obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GENITER; obj.ipfo_size = sizeof(state); obj.ipfo_ptr = &state; state.igi_type = IPFGENITER_STATE; state.igi_nitems = 1; state.igi_data = dst; if (ioctl(state_fd, SIOCGENITER, &obj) != 0) - return NULL; + return(NULL); if (dst->is_next == NULL) { int n = IPFGENITER_STATE; (void) ioctl(ipf_fd,SIOCIPFDELTOK, &n); } } else { if (kmemcpy((char *)dst, (u_long)src, sizeof(*dst))) - return NULL; + return(NULL); } - return dst; + return(dst); } static int fetchfrag( int fd, int type, ipfr_t *frp) { ipfgeniter_t frag; ipfobj_t obj; obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GENITER; obj.ipfo_size = sizeof(frag); obj.ipfo_ptr = &frag; frag.igi_type = type; frag.igi_nitems = 1; frag.igi_data = frp; if (ioctl(fd, SIOCGENITER, &obj)) - return EFAULT; - return 0; + return(EFAULT); + return(0); } static int state_matcharray(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; + return(rv); } static void showtqtable_live(int fd) { ipftq_t table[IPF_TCP_NSTATES]; ipfobj_t obj; 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; if (ioctl(fd, SIOCGTQTAB, &obj) == 0) { printtqtable(table); } } diff --git a/sbin/ipf/ipftest/ip_fil.c b/sbin/ipf/ipftest/ip_fil.c index 4a0af7a33810..0fb59a88f977 100644 --- a/sbin/ipf/ipftest/ip_fil.c +++ b/sbin/ipf/ipftest/ip_fil.c @@ -1,812 +1,812 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #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$"; #endif #include "ipf.h" #include "md5.h" #include "ipt.h" ipf_main_softc_t ipfmain; static struct ifnet **ifneta = NULL; static int nifs = 0; struct rtentry; static void ipf_setifpaddr(struct ifnet *, char *); void init_ifp(void); static int no_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); static int write_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); struct ifaddr { struct sockaddr_storage ifa_addr; }; int ipfattach(softc) ipf_main_softc_t *softc; { - return 0; + return(0); } int ipfdetach(softc) ipf_main_softc_t *softc; { - return 0; + return(0); } /* * Filter ioctl interface. */ int ipfioctl(softc, dev, cmd, data, mode) ipf_main_softc_t *softc; int dev; ioctlcmd_t cmd; caddr_t data; int mode; { int error = 0, unit = 0, uid; uid = getuid(); unit = dev; SPL_NET(s); error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL); if (error != -1) { SPL_X(s); - return error; + return(error); } SPL_X(s); - return error; + return(error); } void ipf_forgetifp(softc, ifp) ipf_main_softc_t *softc; void *ifp; { register frentry_t *f; WRITE_ENTER(&softc->ipf_mutex); for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL); f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL); f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL); f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL); f = f->fr_next) if (f->fr_ifa == ifp) f->fr_ifa = (void *)-1; RWLOCK_EXIT(&softc->ipf_mutex); ipf_nat_sync(softc, ifp); ipf_lookup_sync(softc, ifp); } static int no_output(ifp, m, s, rt) struct rtentry *rt; struct ifnet *ifp; struct mbuf *m; struct sockaddr *s; { - return 0; + return(0); } static int write_output(ifp, m, s, rt) struct rtentry *rt; struct ifnet *ifp; struct mbuf *m; struct sockaddr *s; { char fname[32]; mb_t *mb; ip_t *ip; int fd; mb = (mb_t *)m; ip = MTOD(mb, ip_t *); #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ defined(__FreeBSD__) sprintf(fname, "/tmp/%s", ifp->if_xname); #else sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); #endif fd = open(fname, O_WRONLY|O_APPEND); if (fd == -1) { perror("open"); - return -1; + return(-1); } write(fd, (char *)ip, ntohs(ip->ip_len)); close(fd); - return 0; + return(0); } static void ipf_setifpaddr(ifp, addr) struct ifnet *ifp; char *addr; { struct ifaddr *ifa; #if defined(__NetBSD__) || defined(__FreeBSD__) if (ifp->if_addrlist.tqh_first != NULL) #else if (ifp->if_addrlist != NULL) #endif return; ifa = (struct ifaddr *)malloc(sizeof(*ifa)); #if defined(__NetBSD__) || defined(__FreeBSD__) ifp->if_addrlist.tqh_first = ifa; #else ifp->if_addrlist = ifa; #endif if (ifa != NULL) { struct sockaddr_in *sin; sin = (struct sockaddr_in *)&ifa->ifa_addr; #ifdef USE_INET6 if (index(addr, ':') != NULL) { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; sin6->sin6_family = AF_INET6; /* Abort if bad address. */ switch (inet_pton(AF_INET6, addr, &sin6->sin6_addr)) { case 1: break; case -1: perror("inet_pton"); abort(); break; default: abort(); break; } } else #endif { sin->sin_family = AF_INET; sin->sin_addr.s_addr = inet_addr(addr); if (sin->sin_addr.s_addr == 0) abort(); } } } struct ifnet * get_unit(name, family) char *name; int family; { struct ifnet *ifp, **ifpp, **old_ifneta; char *addr; #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ defined(__FreeBSD__) if (!*name) - return NULL; + return(NULL); if (name == NULL) name = "anon0"; addr = strchr(name, '='); if (addr != NULL) *addr++ = '\0'; for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { if (!strcmp(name, ifp->if_xname)) { if (addr != NULL) ipf_setifpaddr(ifp, addr); - return ifp; + return(ifp); } } #else char *s, ifname[LIFNAMSIZ+1]; if (name == NULL) name = "anon0"; addr = strchr(name, '='); if (addr != NULL) *addr++ = '\0'; for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { COPYIFNAME(family, ifp, ifname); if (!strcmp(name, ifname)) { if (addr != NULL) ipf_setifpaddr(ifp, addr); - return ifp; + return(ifp); } } #endif if (!ifneta) { ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); if (!ifneta) - return NULL; + return(NULL); ifneta[1] = NULL; ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); if (!ifneta[0]) { free(ifneta); - return NULL; + return(NULL); } nifs = 1; } else { old_ifneta = ifneta; nifs++; ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1, sizeof(ifp)); if (!ifneta) { free(old_ifneta); nifs = 0; - return NULL; + return(NULL); } ifneta[nifs] = NULL; ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); if (!ifneta[nifs - 1]) { nifs--; - return NULL; + return(NULL); } } ifp = ifneta[nifs - 1]; #if defined(__NetBSD__) || defined(__FreeBSD__) TAILQ_INIT(&ifp->if_addrlist); #endif #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ defined(__FreeBSD__) (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); #else s = name + strlen(name) - 1; for (; s > name; s--) { if (!ISDIGIT(*s)) { s++; break; } } if ((s > name) && (*s != 0) && ISDIGIT(*s)) { ifp->if_unit = atoi(s); ifp->if_name = (char *)malloc(s - name + 1); (void) strncpy(ifp->if_name, name, s - name); ifp->if_name[s - name] = '\0'; } else { ifp->if_name = strdup(name); ifp->if_unit = -1; } #endif ifp->if_output = (void *)no_output; if (addr != NULL) { ipf_setifpaddr(ifp, addr); } - return ifp; + return(ifp); } char * get_ifname(ifp) struct ifnet *ifp; { static char ifname[LIFNAMSIZ]; #if defined(__NetBSD__) || defined(__FreeBSD__) sprintf(ifname, "%s", ifp->if_xname); #else if (ifp->if_unit != -1) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); else strcpy(ifname, ifp->if_name); #endif - return ifname; + return(ifname); } void init_ifp() { struct ifnet *ifp, **ifpp; char fname[32]; int fd; #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ defined(__FreeBSD__) for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = (void *)write_output; sprintf(fname, "/tmp/%s", ifp->if_xname); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); if (fd == -1) perror("open"); else close(fd); } #else for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { ifp->if_output = (void *)write_output; sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); if (fd == -1) perror("open"); else close(fd); } #endif } int ipf_fastroute(m, mpp, fin, fdp) mb_t *m, **mpp; fr_info_t *fin; frdest_t *fdp; { struct ifnet *ifp; ip_t *ip = fin->fin_ip; frdest_t node; int error = 0; frentry_t *fr; void *sifp; int sout; sifp = fin->fin_ifp; sout = fin->fin_out; fr = fin->fin_fr; ip->ip_sum = 0; if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) && (fdp->fd_type == FRD_DSTLIST)) { bzero(&node, sizeof(node)); ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node); fdp = &node; } ifp = fdp->fd_ptr; if (ifp == NULL) - return 0; /* no routing table out here */ + return(0; /* no routing table out here */); if (fin->fin_out == 0) { fin->fin_ifp = ifp; fin->fin_out = 1; (void) ipf_acctpkt(fin, NULL); fin->fin_fr = NULL; if (!fr || !(fr->fr_flags & FR_RETMASK)) { u_32_t pass; (void) ipf_state_check(fin, &pass); } switch (ipf_nat_checkout(fin, NULL)) { case 0 : break; case 1 : ip->ip_sum = 0; break; case -1 : error = -1; goto done; break; } } m->mb_ifp = ifp; printpacket(fin->fin_out, m); (*ifp->if_output)(ifp, (void *)m, NULL, 0); done: fin->fin_ifp = sifp; fin->fin_out = sout; - return error; + return(error); } int ipf_send_reset(fin) fr_info_t *fin; { ipfkverbose("- TCP RST sent\n"); - return 0; + return(0); } int ipf_send_icmp_err(type, fin, dst) int type; fr_info_t *fin; int dst; { ipfkverbose("- ICMP unreachable sent\n"); - return 0; + return(0); } void m_freem(m) mb_t *m; { return; } void m_copydata(m, off, len, cp) mb_t *m; int off, len; caddr_t cp; { bcopy((char *)m + off, cp, len); } int ipfuiomove(buf, len, rwflag, uio) caddr_t buf; int len, rwflag; struct uio *uio; { int left, ioc, num, offset; struct iovec *io; char *start; if (rwflag == UIO_READ) { left = len; ioc = 0; offset = uio->uio_offset; while ((left > 0) && (ioc < uio->uio_iovcnt)) { io = uio->uio_iov + ioc; num = io->iov_len; if (num > left) num = left; start = (char *)io->iov_base + offset; if (start > (char *)io->iov_base + io->iov_len) { offset -= io->iov_len; ioc++; continue; } bcopy(buf, start, num); uio->uio_resid -= num; uio->uio_offset += num; left -= num; if (left > 0) ioc++; } if (left > 0) - return EFAULT; + return(EFAULT); } - return 0; + return(0); } u_32_t ipf_newisn(fin) fr_info_t *fin; { static int iss_seq_off = 0; u_char hash[16]; u_32_t newiss; MD5_CTX ctx; /* * Compute the base value of the ISS. It is a hash * of (saddr, sport, daddr, dport, secret). */ MD5Init(&ctx); MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, sizeof(fin->fin_fi.fi_src)); MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, sizeof(fin->fin_fi.fi_dst)); MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ MD5Final(hash, &ctx); memcpy(&newiss, hash, sizeof(newiss)); /* * Now increment our "timer", and add it in to * the computed value. * * XXX Use `addin'? * XXX TCP_ISSINCR too large to use? */ iss_seq_off += 0x00010000; newiss += iss_seq_off; - return newiss; + return(newiss); } /* ------------------------------------------------------------------------ */ /* Function: ipf_nextipid */ /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ /* Parameters: fin(I) - pointer to packet information */ /* */ /* Returns the next IPv4 ID to use for this packet. */ /* ------------------------------------------------------------------------ */ inline u_short ipf_nextipid(fin) fr_info_t *fin; { static u_short ipid = 0; ipf_main_softc_t *softc = fin->fin_main_soft; u_short id; MUTEX_ENTER(&softc->ipf_rw); if (fin->fin_pktnum != 0) { /* * The -1 is for aligned test results. */ id = (fin->fin_pktnum - 1) & 0xffff; } else { } id = ipid++; MUTEX_EXIT(&softc->ipf_rw); - return id; + return(id); } inline int ipf_checkv4sum(fin) fr_info_t *fin; { if (fin->fin_flx & FI_SHORT) - return 1; + return(1); if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; - return -1; + return(-1); } - return 0; + return(0); } #ifdef USE_INET6 inline int ipf_checkv6sum(fin) fr_info_t *fin; { if (fin->fin_flx & FI_SHORT) - return 1; + return(1); if (ipf_checkl4sum(fin) == -1) { fin->fin_flx |= FI_BAD; - return -1; + return(-1); } - return 0; + return(0); } #endif #if 0 /* * See above for description, except that all addressing is in user space. */ int copyoutptr(softc, src, dst, size) void *src, *dst; size_t size; { caddr_t ca; bcopy(dst, (char *)&ca, sizeof(ca)); bcopy(src, ca, size); - return 0; + return(0); } /* * See above for description, except that all addressing is in user space. */ int copyinptr(src, dst, size) void *src, *dst; size_t size; { caddr_t ca; bcopy(src, (char *)&ca, sizeof(ca)); bcopy(ca, dst, size); - return 0; + return(0); } #endif /* - * return the first IP Address associated with an interface +* return the first IP Address associated with an interface */ int ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask) ipf_main_softc_t *softc; int v, atype; void *ifptr; i6addr_t *inp, *inpmask; { struct ifnet *ifp = ifptr; struct ifaddr *ifa; #if defined(__NetBSD__) || defined(__FreeBSD__) ifa = ifp->if_addrlist.tqh_first; #else ifa = ifp->if_addrlist; #endif if (ifa != NULL) { if (v == 4) { struct sockaddr_in *sin, mask; mask.sin_addr.s_addr = 0xffffffff; sin = (struct sockaddr_in *)&ifa->ifa_addr; - return ipf_ifpfillv4addr(atype, sin, &mask, - &inp->in4, &inpmask->in4); + return(ipf_ifpfillv4addr(atype, sin, &mask, + &inp->in4, &inpmask->in4)); } #ifdef USE_INET6 if (v == 6) { struct sockaddr_in6 *sin6, mask; sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr; ((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff; ((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff; ((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff; ((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff; - return ipf_ifpfillv6addr(atype, sin6, &mask, - inp, inpmask); + return(ipf_ifpfillv6addr(atype, sin6, &mask, + inp, inpmask)); } #endif } - return 0; + return(0); } /* * This function is not meant to be random, rather just produce a * sequence of numbers that isn't linear to show "randomness". */ u_32_t ipf_random() { static unsigned int last = 0xa5a5a5a5; static int calls = 0; int number; calls++; /* * These are deliberately chosen to ensure that there is some * attempt to test whether the output covers the range in test n18. */ switch (calls) { case 1 : number = 0; break; case 2 : number = 4; break; case 3 : number = 3999; break; case 4 : number = 4000; break; case 5 : number = 48999; break; case 6 : number = 49000; break; default : number = last; last *= calls; last++; number ^= last; break; } - return number; + return(number); } int ipf_verifysrc(fin) fr_info_t *fin; { - return 1; + return(1); } int ipf_inject(fin, m) fr_info_t *fin; mb_t *m; { FREE_MB_T(m); - return 0; + return(0); } u_int ipf_pcksum(fin, hlen, sum) fr_info_t *fin; int hlen; u_int sum; { u_short *sp; u_int sum2; int slen; slen = fin->fin_plen - hlen; sp = (u_short *)((u_char *)fin->fin_ip + hlen); for (; slen > 1; slen -= 2) sum += *sp++; if (slen) sum += ntohs(*(u_char *)sp << 8); while (sum > 0xffff) sum = (sum & 0xffff) + (sum >> 16); sum2 = (u_short)(~sum & 0xffff); - return sum2; + return(sum2); } void * ipf_pullup(m, fin, plen) mb_t *m; fr_info_t *fin; int plen; { if (M_LEN(m) >= plen) - return fin->fin_ip; + return(fin->fin_ip); /* * Fake ipf_pullup failing */ fin->fin_reason = FRB_PULLUP; *fin->fin_mp = NULL; fin->fin_m = NULL; fin->fin_ip = NULL; - return NULL; + return(NULL); } diff --git a/sbin/ipf/ipftest/ipftest.1 b/sbin/ipf/ipftest/ipftest.1 index 10232d338d9f..d240967294f5 100644 --- a/sbin/ipf/ipftest/ipftest.1 +++ b/sbin/ipf/ipftest/ipftest.1 @@ -1,205 +1,205 @@ .\" $FreeBSD$ .TH ipftest 1 .SH NAME ipftest \- test packet filter rules with arbitrary input. .SH SYNOPSIS .B ipftest [ .B \-6bCdDoRvx ] [ .B \-F input-format ] [ .B \-i ] [ .B \-I interface ] [ .B \-l ] [ .B \-N ] [ .B \-P ] [ .B \-r ] [ .B \-S ] [ .B \-T ] .SH DESCRIPTION .PP \fBipftest\fP is provided for the purpose of being able to test a set of filter rules without having to put them in place, in operation and proceed to test their effectiveness. The hope is that this minimises disruptions in providing a secure IP environment. .PP \fBipftest\fP will parse any standard ruleset for use with \fBipf\fP, \fBipnat\fP and/or \fBippool\fP and apply input, returning output as to the result. However, \fBipftest\fP -will return one of three values for packets passed through the filter: +will( return one of three values for packets passed through the filter:); pass, block or nomatch. This is intended to give the operator a better idea of what is happening with packets passing through their filter ruleset. .PP At least one of \fB\-N\fP, \fB-P\fP or \fB\-r\fP must be specified. .SH OPTIONS .TP .B \-6 Use IPv6. .TP .B \-b Cause the output to be a brief summary (one-word) of the result of passing the packet through the filter; either "pass", "block" or "nomatch". This is used in the regression testing. .TP .B \-C Force the checksums to be (re)calculated for all packets being input into \fBipftest\fP. This may be necessary if pcap files from tcpdump are being fed in where there are partial checksums present due to hardware offloading. .TP .B \-d Turn on filter rule debugging. Currently, this only shows you what caused the rule to not match in the IP header checking (addresses/netmasks, etc). .TP .B \-D Dump internal tables before exiting. This excludes log messages. .TP .B \-F This option is used to select which input format the input file is in. The following formats are available: etherfind, hex, pcap, snoop, tcpdump,text. .RS .TP .B etherfind The input file is to be text output from etherfind. The text formats which are currently supported are those which result from the following etherfind option combinations: .PP .nf etherfind -n etherfind -n -t .fi .TP .B hex The input file is to be hex digits, representing the binary makeup of the packet. No length correction is made, if an incorrect length is put in the IP header. A packet may be broken up over several lines of hex digits, a blank line indicating the end of the packet. It is possible to specify both the interface name and direction of the packet (for filtering purposes) at the start of the line using this format: [direction,interface] To define a packet going in on le0, we would use \fB[in,le0]\fP - the []'s are required and part of the input syntax. .HP .B pcap The input file specified by \fB\-i\fP is a binary file produced using libpcap (i.e., tcpdump version 3). Packets are read from this file as being input (for rule purposes). An interface maybe specified using \fB\-I\fP. .TP .B snoop The input file is to be in "snoop" format (see RFC 1761). Packets are read from this file and used as input from any interface. This is perhaps the most useful input type, currently. .TP .B tcpdump The input file is to be text output from tcpdump. The text formats which are currently supported are those which result from the following tcpdump option combinations: .PP .nf tcpdump -n tcpdump -nq tcpdump -nqt tcpdump -nqtt tcpdump -nqte .fi .TP .B text The input file is in \fBipftest\fP text input format. This is the default if no \fB\-F\fP argument is specified. The format used is as follows: .nf "in"|"out" "on" if ["tcp"|"udp"|"icmp"] srchost[,srcport] dsthost[,destport] [FSRPAU] .fi .PP This allows for a packet going "in" or "out" of an interface (if) to be generated, being one of the three main protocols (optionally), and if either TCP or UDP, a port parameter is also expected. If TCP is selected, it is possible to (optionally) supply TCP flags at the end. Some examples are: .nf # a UDP packet coming in on le0 in on le0 udp 10.1.1.1,2210 10.2.1.5,23 # an IP packet coming in on le0 from localhost - hmm :) in on le0 localhost 10.4.12.1 # a TCP packet going out of le0 with the SYN flag set. out on le0 tcp 10.4.12.1,2245 10.1.1.1,23 S .fi .RE .DT .TP .BR \-i \0 Specify the filename from which to take input. Default is stdin. .TP .BR \-I \0 Set the interface name (used in rule matching) to be the name supplied. This is useful where it is not otherwise possible to associate a packet with an interface. Normal "text packets" can override this setting. .TP .BR \-l \0 Dump log messages generated during testing to the specified file. .TP .BR \-N \0 Specify the filename from which to read NAT rules in \fBipnat\fP(5) format. .TP .B \-o Save output packets that would have been written to each interface in a file /tmp/\fIinterface_name\fP in raw format. .TP .BR \-P \0 Read IP pool configuration information in \fBippool\fP(5) format from the specified file. .TP .BR \-r \0 Specify the filename from which to read filter rules in \fBipf\fP(5) format. .TP .B \-R Don't attempt to convert IP addresses to hostnames. .TP .BR \-S \0 The IP address specifived with this option is used by ipftest to determine whether a packet should be treated as "input" or "output". If the source address in an IP packet matches then it is considered to be inbound. If it does not match then it is considered to be outbound. This is primarily for use with tcpdump (pcap) files where there is no in/out information saved with each packet. .TP .BR \-T \0 This option simulates the run-time changing of IPFilter kernel variables available with the \fB\-T\fP option of \fBipf\fP. The optionlist parameter is a comma separated list of tuning commands. A tuning command is either "list" (retrieve a list of all variables in the kernel, their maximum, minimum and current value), a single variable name (retrieve its current value) and a variable name with a following assignment to set a new value. See \fBipf\fP(8) for examples. .TP .B \-v Verbose mode. This provides more information about which parts of rule matching the input packet passes and fails. .TP .B \-x Print a hex dump of each packet before printing the decoded contents. .SH SEE ALSO ipf(5), ipf(8), snoop(1m), tcpdump(8), etherfind(8c) .SH BUGS Not all of the input formats are sufficiently capable of introducing a wide enough variety of packets for them to be all useful in testing. diff --git a/sbin/ipf/ipftest/ipftest.c b/sbin/ipf/ipftest/ipftest.c index df77dd650ffa..c7bdfd78c4a3 100644 --- a/sbin/ipf/ipftest/ipftest.c +++ b/sbin/ipf/ipftest/ipftest.c @@ -1,715 +1,715 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" #include "ipt.h" #include #include #if !defined(lint) static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif extern char *optarg; extern struct ipread pcap, iptext, iphex; extern struct ifnet *get_unit(char *, int); extern void init_ifp(void); extern ipnat_t *natparse(char *, int); extern hostmap_t **ipf_hm_maptable; extern hostmap_t *ipf_hm_maplist; 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_authlk; ipfrwlock_t ipf_tokens; int opts = OPT_DONTOPEN; int use_inet6 = 0; int docksum = 0; int pfil_delayed_copy = 0; int main(int, char *[]); int loadrules(char *, int); int kmemcpy(char *, long, int); int kstrncpy(char *, long, int n); int blockreason; void dumpnat(void *); void dumpgroups(ipf_main_softc_t *); void dumprules(frentry_t *); void drain_log(char *); void fixv4sums(mb_t *, ip_t *); int ipftestioctl(int, ioctlcmd_t, ...); int ipnattestioctl(int, ioctlcmd_t, ...); int ipstatetestioctl(int, ioctlcmd_t, ...); int ipauthtestioctl(int, ioctlcmd_t, ...); int ipscantestioctl(int, ioctlcmd_t, ...); int ipsynctestioctl(int, ioctlcmd_t, ...); int ipooltestioctl(int, ioctlcmd_t, ...); static ioctlfunc_t iocfunctions[IPL_LOGSIZE] = { ipftestioctl, ipnattestioctl, ipstatetestioctl, ipauthtestioctl, ipsynctestioctl, ipscantestioctl, ipooltestioctl, NULL }; static ipf_main_softc_t *softc = NULL; int main(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, *n; ip_t *ip; m = &mb; dir = 0; dump = 0; hlen = 0; loaded = 0; r = &iptext; iface = NULL; logout = NULL; datain = NULL; sip.s_addr = 0; ifname = "anon0"; initparse(); 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) { case '6' : #ifdef USE_INET6 use_inet6 = 1; #else fprintf(stderr, "IPv6 not supported\n"); exit(1); #endif break; case 'b' : opts |= OPT_BRIEF; break; case 'd' : opts |= OPT_DEBUG; break; case 'C' : docksum = 1; break; case 'D' : dump = 1; break; case 'F' : if (strcasecmp(optarg, "pcap") == 0) r = &pcap; else if (strcasecmp(optarg, "hex") == 0) r = &iphex; else if (strcasecmp(optarg, "text") == 0) r = &iptext; break; case 'i' : datain = optarg; break; case 'I' : ifname = optarg; break; case 'l' : logout = optarg; break; case 'N' : if (ipnat_parsefile(-1, ipnat_addrule, ipnattestioctl, optarg) == -1) - return -1; + return(-1); loaded = 1; opts |= OPT_NAT; break; case 'o' : opts |= OPT_SAVEOUT; break; case 'P' : if (ippool_parsefile(-1, optarg, ipooltestioctl) == -1) - return -1; + return(-1); loaded = 1; break; case 'r' : if (ipf_parsefile(-1, ipf_addrule, iocfunctions, optarg) == -1) - return -1; + return(-1); loaded = 1; break; case 'S' : sip.s_addr = inet_addr(optarg); break; case 'R' : opts |= OPT_NORESOLVE; break; case 'T' : ipf_dotuning(-1, optarg, ipftestioctl); break; case 'v' : opts |= OPT_VERBOSE; break; case 'x' : opts |= OPT_HEX; break; } if (loaded == 0) { (void)fprintf(stderr,"no rules loaded\n"); exit(-1); } if (opts & OPT_SAVEOUT) init_ifp(); if (datain) fd = (*r->r_open)(datain); else fd = (*r->r_open)("-"); 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) { if ((iface == NULL) || (*iface == '\0')) iface = ifname; ip = MTOD(m, ip_t *); ifp = get_unit(iface, IP_V(ip)); if (IP_V(ip) == 4) { if ((r->r_flags & R_DO_CKSUM) || docksum) fixv4sums(m, ip); hlen = IP_HL(ip) << 2; if (sip.s_addr) dir = !(sip.s_addr == ip->ip_src.s_addr); } #ifdef USE_INET6 else hlen = sizeof(ip6_t); #endif /* ipfr_slowtimer(); */ blockreason = 0; m = &mb; m->mb_ifp = ifp; m->mb_len = i; i = ipf_check(softc, ip, hlen, ifp, dir, &m); if ((opts & OPT_NAT) == 0) switch (i) { case -4 : (void)printf("preauth"); break; case -3 : (void)printf("account"); break; case -2 : (void)printf("auth"); break; case -1 : (void)printf("block"); break; case 0 : (void)printf("pass"); break; case 1 : if (m == NULL) (void)printf("bad-packet"); else (void)printf("nomatch"); break; case 3 : (void)printf("block return-rst"); break; case 4 : (void)printf("block return-icmp"); break; case 5 : (void)printf("block return-icmp-as-dest"); break; default : - (void)printf("recognised return %#x\n", i); + (void)printf("recognised( return %#x\n", i)); break; } if (!(opts & OPT_BRIEF)) { putchar(' '); if (m != NULL) printpacket(dir, m); else printpacket(dir, &mb); printf("--------------"); } 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)) (*ifp->if_output)(ifp, (void *)m, NULL, 0); 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; if (iface != ifname) { free(iface); iface = ifname; } m = &mb; m->mb_data = (char *)m->mb_buf; } if (i != 0) fprintf(stderr, "readip failed: %d\n", i); (*r->r_close)(); if (logout != NULL) { drain_log(logout); } if (dump == 1) { dumpnat(softc->ipf_nat_soft); ipf_state_dump(softc, softc->ipf_state_soft); ipf_lookup_dump(softc, softc->ipf_state_soft); dumpgroups(softc); } 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; + return(0); } int ipftestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGIPF, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) fprintf(stderr, "ipfioctl(IPF,%#x,%p) = %d (%d)\n", (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipnattestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGNAT, cmd, data, FWRITE|FREAD); if (opts & OPT_DEBUG) fprintf(stderr, "ipfioctl(NAT,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipstatetestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGSTATE, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "ipfioctl(STATE,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipauthtestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGAUTH, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "ipfioctl(AUTH,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipscantestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGSCAN, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "ipfioctl(SCAN,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipsynctestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGSYNC, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "ipfioctl(SYNC,%#x,%p) = %d\n", (u_int)cmd, data, i); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int ipooltestioctl(int dev, ioctlcmd_t cmd, ...) { caddr_t data; va_list ap; int i; dev = dev; /* gcc -Wextra */ va_start(ap, cmd); data = va_arg(ap, caddr_t); va_end(ap); i = ipfioctl(softc, IPL_LOGLOOKUP, cmd, data, FWRITE|FREAD); if ((opts & OPT_DEBUG) || (i != 0)) fprintf(stderr, "ipfioctl(POOL,%#x,%p) = %d (%d)\n", (u_int)cmd, data, i, softc->ipf_interror); if (i != 0) { errno = i; - return -1; + return(-1); } - return 0; + return(0); } int kmemcpy(char *addr, long offset, int size) { bcopy((char *)offset, addr, size); - return 0; + return(0); } int kstrncpy(char *buf, long pos, int n) { char *ptr; ptr = (char *)pos; while ((n > 0) && (*buf++ = *ptr++)) ; - return 0; + return(0); } /* * Display the built up NAT table rules and mapping entries. */ void dumpnat(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 = 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 = softn->ipf_nat_instances; nat; nat = nat->nat_next) { printactivenat(nat, opts, 0); if (nat->nat_aps) printf("\tproxy active\n"); } printf("\nHostmap table:\n"); for (hm = softn->ipf_hm_maplist; hm != NULL; hm = hm->hm_next) printhostmap(hm, hm->hm_hv); } void dumpgroups(ipf_main_softc_t *softc) { frgroup_t *fg; int i; printf("List of groups configured (set 0)\n"); for (i = 0; i < IPL_LOGSIZE; i++) 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); dumprules(fg->fg_start); } printf("List of groups configured (set 1)\n"); for (i = 0; i < IPL_LOGSIZE; i++) 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); 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(frentry_t *rulehead) { frentry_t *fr; for (fr = rulehead; fr != NULL; fr = fr->fr_next) { #ifdef USE_QUAD_T printf("%"PRIu64" ",(unsigned long long)fr->fr_hits); #else printf("%ld ", fr->fr_hits); #endif printfr(fr, ipftestioctl); } } void drain_log(char *filename) { char buffer[DEFAULT_IPFLOGSIZE]; struct iovec iov; struct uio uio; size_t resid; int fd, i; fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644); if (fd == -1) { perror("drain_log:open"); return; } for (i = 0; i <= IPL_LOGMAX; i++) while (1) { bzero((char *)&iov, sizeof(iov)); iov.iov_base = buffer; iov.iov_len = sizeof(buffer); bzero((char *)&uio, sizeof(uio)); uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = iov.iov_len; resid = uio.uio_resid; if (ipf_log_read(softc, i, &uio) == 0) { /* * If nothing was read then break out. */ if (uio.uio_resid == resid) break; write(fd, buffer, resid - uio.uio_resid); } else break; } close(fd); } void fixv4sums(mb_t *m, ip_t *ip) { u_char *csump, *hdr, p; fr_info_t tmp; int len; p = 0; len = 0; bzero((char *)&tmp, sizeof(tmp)); csump = (u_char *)ip; 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 (p) { case IPPROTO_TCP : hdr = csump; csump += offsetof(tcphdr_t, th_sum); break; case IPPROTO_UDP : hdr = csump; csump += offsetof(udphdr_t, uh_sum); break; case IPPROTO_ICMP : hdr = csump; csump += offsetof(icmphdr_t, icmp_cksum); break; default : csump = NULL; hdr = NULL; 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(&tmp, ip, p, hdr); } } void ip_fillid(struct ip *ip) { static uint16_t ip_id; ip->ip_id = ip_id++; } diff --git a/sbin/ipf/iplang/iplang_l.l b/sbin/ipf/iplang/iplang_l.l index ba807edb9a70..58538d8e4d1c 100644 --- a/sbin/ipf/iplang/iplang_l.l +++ b/sbin/ipf/iplang/iplang_l.l @@ -1,317 +1,317 @@ /* $FreeBSD$ */ %{ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include #if defined(__SVR4) || defined(__sysv__) #include #endif #include #include #include #include "iplang_y.h" #include "ipf.h" #ifndef __P # define __P(x) x #endif extern int opts; int lineNum = 0, ipproto = 0, oldipproto = 0, next = -1, laststate = 0; int *prstack = NULL, numpr = 0, state = 0, token = 0; void yyerror(char *); void push_proto(void); void pop_proto(void); int next_state(int, int); int next_item(int); int save_token(void); void swallow(void); int yylex(void); struct lwordtab { char *word; int state; int next; }; struct lwordtab words[] = { { "interface", IL_INTERFACE, -1 }, { "iface", IL_INTERFACE, -1 }, { "name", IL_IFNAME, IL_TOKEN }, { "ifname", IL_IFNAME, IL_TOKEN }, { "router", IL_DEFROUTER, IL_TOKEN }, { "mtu", IL_MTU, IL_NUMBER }, { "eaddr", IL_EADDR, IL_TOKEN }, { "v4addr", IL_V4ADDR, IL_TOKEN }, { "ipv4", IL_IPV4, -1 }, { "v", IL_V4V, IL_TOKEN }, { "proto", IL_V4PROTO, IL_TOKEN }, { "hl", IL_V4HL, IL_TOKEN }, { "id", IL_V4ID, IL_TOKEN }, { "ttl", IL_V4TTL, IL_TOKEN }, { "tos", IL_V4TOS, IL_TOKEN }, { "src", IL_V4SRC, IL_TOKEN }, { "dst", IL_V4DST, IL_TOKEN }, { "opt", IL_OPT, -1 }, { "len", IL_LEN, IL_TOKEN }, { "off", IL_OFF, IL_TOKEN }, { "sum", IL_SUM, IL_TOKEN }, { "tcp", IL_TCP, -1 }, { "sport", IL_SPORT, IL_TOKEN }, { "dport", IL_DPORT, IL_TOKEN }, { "seq", IL_TCPSEQ, IL_TOKEN }, { "ack", IL_TCPACK, IL_TOKEN }, { "flags", IL_TCPFL, IL_TOKEN }, { "urp", IL_TCPURP, IL_TOKEN }, { "win", IL_TCPWIN, IL_TOKEN }, { "udp", IL_UDP, -1 }, { "send", IL_SEND, -1 }, { "via", IL_VIA, IL_TOKEN }, { "arp", IL_ARP, -1 }, { "data", IL_DATA, -1 }, { "value", IL_DVALUE, IL_TOKEN }, { "file", IL_DFILE, IL_TOKEN }, { "nop", IL_IPO_NOP, -1 }, { "eol", IL_IPO_EOL, -1 }, { "rr", IL_IPO_RR, -1 }, { "zsu", IL_IPO_ZSU, -1 }, { "mtup", IL_IPO_MTUP, -1 }, { "mtur", IL_IPO_MTUR, -1 }, { "encode", IL_IPO_ENCODE, -1 }, { "ts", IL_IPO_TS, -1 }, { "tr", IL_IPO_TR, -1 }, { "sec", IL_IPO_SEC, -1 }, { "secclass", IL_IPO_SECCLASS, IL_TOKEN }, { "lsrr", IL_IPO_LSRR, -1 }, { "esec", IL_IPO_ESEC, -1 }, { "cipso", IL_IPO_CIPSO, -1 }, { "satid", IL_IPO_SATID, -1 }, { "ssrr", IL_IPO_SSRR, -1 }, { "addext", IL_IPO_ADDEXT, -1 }, { "visa", IL_IPO_VISA, -1 }, { "imitd", IL_IPO_IMITD, -1 }, { "eip", IL_IPO_EIP, -1 }, { "finn", IL_IPO_FINN, -1 }, { "mss", IL_TCPO_MSS, IL_TOKEN }, { "wscale", IL_TCPO_WSCALE, IL_TOKEN }, { "reserv-4", IL_IPS_RESERV4, -1 }, { "topsecret", IL_IPS_TOPSECRET, -1 }, { "secret", IL_IPS_SECRET, -1 }, { "reserv-3", IL_IPS_RESERV3, -1 }, { "confid", IL_IPS_CONFID, -1 }, { "unclass", IL_IPS_UNCLASS, -1 }, { "reserv-2", IL_IPS_RESERV2, -1 }, { "reserv-1", IL_IPS_RESERV1, -1 }, { "icmp", IL_ICMP, -1 }, { "type", IL_ICMPTYPE, -1 }, { "code", IL_ICMPCODE, -1 }, { "echorep", IL_ICMP_ECHOREPLY, -1 }, { "unreach", IL_ICMP_UNREACH, -1 }, { "squench", IL_ICMP_SOURCEQUENCH, -1 }, { "redir", IL_ICMP_REDIRECT, -1 }, { "echo", IL_ICMP_ECHO, -1 }, { "routerad", IL_ICMP_ROUTERADVERT, -1 }, { "routersol", IL_ICMP_ROUTERSOLICIT, -1 }, { "timex", IL_ICMP_TIMXCEED, -1 }, { "paramprob", IL_ICMP_PARAMPROB, -1 }, { "timest", IL_ICMP_TSTAMP, -1 }, { "timestrep", IL_ICMP_TSTAMPREPLY, -1 }, { "inforeq", IL_ICMP_IREQ, -1 }, { "inforep", IL_ICMP_IREQREPLY, -1 }, { "maskreq", IL_ICMP_MASKREQ, -1 }, { "maskrep", IL_ICMP_MASKREPLY, -1 }, { "net-unr", IL_ICMP_UNREACH_NET, -1 }, { "host-unr", IL_ICMP_UNREACH_HOST, -1 }, { "proto-unr", IL_ICMP_UNREACH_PROTOCOL, -1 }, { "port-unr", IL_ICMP_UNREACH_PORT, -1 }, { "needfrag", IL_ICMP_UNREACH_NEEDFRAG, -1 }, { "srcfail", IL_ICMP_UNREACH_SRCFAIL, -1 }, { "net-unk", IL_ICMP_UNREACH_NET_UNKNOWN, -1 }, { "host-unk", IL_ICMP_UNREACH_HOST_UNKNOWN, -1 }, { "isolate", IL_ICMP_UNREACH_ISOLATED, -1 }, { "net-prohib", IL_ICMP_UNREACH_NET_PROHIB, -1 }, { "host-prohib", IL_ICMP_UNREACH_HOST_PROHIB, -1 }, { "net-tos", IL_ICMP_UNREACH_TOSNET, -1 }, { "host-tos", IL_ICMP_UNREACH_TOSHOST, -1 }, { "filter-prohib", IL_ICMP_UNREACH_FILTER_PROHIB, -1 }, { "host-preced", IL_ICMP_UNREACH_HOST_PRECEDENCE, -1 }, { "cutoff-preced", IL_ICMP_UNREACH_PRECEDENCE_CUTOFF, -1 }, { "net-redir", IL_ICMP_REDIRECT_NET, -1 }, { "host-redir", IL_ICMP_REDIRECT_HOST, -1 }, { "tos-net-redir", IL_ICMP_REDIRECT_TOSNET, -1 }, { "tos-host-redir", IL_ICMP_REDIRECT_TOSHOST, -1 }, { "intrans", IL_ICMP_TIMXCEED_INTRANS, -1 }, { "reass", IL_ICMP_TIMXCEED_REASS, -1 }, { "optabsent", IL_ICMP_PARAMPROB_OPTABSENT, -1 }, { "otime", IL_ICMP_OTIME, -1 }, { "rtime", IL_ICMP_RTIME, -1 }, { "ttime", IL_ICMP_TTIME, -1 }, { "icmpseq", IL_ICMP_SEQ, -1 }, { "icmpid", IL_ICMP_SEQ, -1 }, { ".", IL_DOT, -1 }, { NULL, 0, 0 } }; %} white [ \t\r]+ %% {white} ; \n { lineNum++; swallow(); } -\{ { push_proto(); return next_item('{'); } -\} { pop_proto(); return next_item('}'); } -; { return next_item(';'); } -[0-9]+ { return next_item(IL_NUMBER); } -[0-9a-fA-F] { return next_item(IL_HEXDIGIT); } -: { return next_item(IL_COLON); } -#[^\n]* { return next_item(IL_COMMENT); } -[^ \{\}\n\t;:{}]* { return next_item(IL_TOKEN); } -\"[^\"]*\" { return next_item(IL_TOKEN); } +\{ {( push_proto(); return next_item('{'); }); +\} {( pop_proto(); return next_item('}'); }); +; {( return next_item(';'); }); +[0-9]+ {( return next_item(IL_NUMBER); }); +[0-9a-fA-F] {( return next_item(IL_HEXDIGIT); }); +: {( return next_item(IL_COLON); }); +#[^\n]* {( return next_item(IL_COMMENT); }); +[^( \{\}\n\t;:{}]* { return next_item(IL_TOKEN); }); +\"[^\"]*\" {( return next_item(IL_TOKEN); }); %% void yyerror(msg) char *msg; { fprintf(stderr, "%s error at \"%s\", line %d\n", msg, yytext, lineNum + 1); exit(1); } void push_proto(void) { numpr++; if (!prstack) prstack = (int *)malloc(sizeof(int)); else prstack = (int *)reallocarray((char *)prstack, numpr, sizeof(int)); prstack[numpr - 1] = oldipproto; } void pop_proto(void) { numpr--; ipproto = prstack[numpr]; if (!numpr) { free(prstack); prstack = NULL; return; } prstack = (int *)realloc((char *)prstack, numpr * sizeof(int)); } int save_token(void) { yylval.str = strdup((char *)yytext); - return IL_TOKEN; + return(IL_TOKEN); } int next_item(int nstate) { struct lwordtab *wt; if (opts & OPT_DEBUG) printf("text=[%s] id=%d next=%d\n", yytext, nstate, next); if (next == IL_TOKEN) { next = -1; - return save_token(); + return(save_token()); } token++; for (wt = words; wt->word; wt++) if (!strcasecmp(wt->word, (char *)yytext)) - return next_state(wt->state, wt->next); + return(next_state(wt->state, wt->next)); if (opts & OPT_DEBUG) printf("unknown keyword=[%s]\n", yytext); next = -1; if (nstate == IL_NUMBER) yylval.num = atoi((char *)yytext); token++; - return nstate; + return(nstate); } int next_state(int nstate, int fornext) { next = fornext; switch (nstate) { case IL_IPV4 : case IL_TCP : case IL_UDP : case IL_ICMP : case IL_DATA : case IL_INTERFACE : case IL_ARP : oldipproto = ipproto; ipproto = nstate; break; case IL_SUM : if (ipproto == IL_IPV4) nstate = IL_V4SUM; else if (ipproto == IL_TCP) nstate = IL_TCPSUM; else if (ipproto == IL_UDP) nstate = IL_UDPSUM; break; case IL_OPT : if (ipproto == IL_IPV4) nstate = IL_V4OPT; else if (ipproto == IL_TCP) nstate = IL_TCPOPT; break; case IL_IPO_NOP : if (ipproto == IL_TCP) nstate = IL_TCPO_NOP; break; case IL_IPO_EOL : if (ipproto == IL_TCP) nstate = IL_TCPO_EOL; break; case IL_IPO_TS : if (ipproto == IL_TCP) nstate = IL_TCPO_TS; break; case IL_OFF : if (ipproto == IL_IPV4) nstate = IL_V4OFF; else if (ipproto == IL_TCP) nstate = IL_TCPOFF; break; case IL_LEN : if (ipproto == IL_IPV4) nstate = IL_V4LEN; else if (ipproto == IL_UDP) nstate = IL_UDPLEN; break; } - return nstate; + return(nstate); } void swallow(void) { int c; c = input(); if (c == '#') { while ((c != '\n') && (c != EOF)) c = input(); } if (c != EOF) unput(c); } diff --git a/sbin/ipf/iplang/iplang_y.y b/sbin/ipf/iplang/iplang_y.y index c098b98d6a75..e6c88ddcd9bc 100644 --- a/sbin/ipf/iplang/iplang_y.y +++ b/sbin/ipf/iplang/iplang_y.y @@ -1,1757 +1,1757 @@ /* $FreeBSD$ */ %{ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp $ * $FreeBSD$ */ #include #include #include #if !defined(__SVR4) && !defined(__svr4__) # include #else # include #endif #include #include #include #include #include #include #include #include #include #include #include #include # include # include # include #include #include #include #include #include #include "ipsend.h" #include "ip_compat.h" #include "ipf.h" #include "iplang.h" extern int opts; extern struct ipopt_names ionames[]; extern int state, state, lineNum, token; extern int yylineno; extern char yytext[]; extern FILE *yyin; int yylex __P((void)); #define YYDEBUG 1 int yydebug = 1; iface_t *iflist = NULL, **iftail = &iflist; iface_t *cifp = NULL; arp_t *arplist = NULL, **arptail = &arplist, *carp = NULL; struct in_addr defrouter; send_t sending; char *sclass = NULL; u_short c_chksum(u_short *, u_int, u_long); u_long p_chksum(u_short *, u_int); u_long ipbuffer[67584/sizeof(u_long)]; /* 66K */ aniphdr_t *aniphead = NULL, *canip = NULL, **aniptail = &aniphead; ip_t *ip = NULL; udphdr_t *udp = NULL; tcphdr_t *tcp = NULL; icmphdr_t *icmp = NULL; struct statetoopt { int sto_st; int sto_op; }; struct in_addr getipv4addr(char *arg); u_short getportnum(char *, char *); struct ether_addr *geteaddr(char *, struct ether_addr *); void *new_header(int); void free_aniplist(void); void inc_anipheaders(int); void new_data(void); void set_datalen(char **); void set_datafile(char **); void set_data(char **); void new_packet(void); void set_ipv4proto(char **); void set_ipv4src(char **); void set_ipv4dst(char **); void set_ipv4off(char **); void set_ipv4v(char **); void set_ipv4hl(char **); void set_ipv4ttl(char **); void set_ipv4tos(char **); void set_ipv4id(char **); void set_ipv4sum(char **); void set_ipv4len(char **); void new_tcpheader(void); void set_tcpsport(char **); void set_tcpdport(char **); void set_tcpseq(char **); void set_tcpack(char **); void set_tcpoff(char **); void set_tcpurp(char **); void set_tcpwin(char **); void set_tcpsum(char **); void set_tcpflags(char **); void set_tcpopt(int, char **); void end_tcpopt(void); void new_udpheader(void); void set_udplen(char **); void set_udpsum(char **); void prep_packet(void); void packet_done(void); void new_interface(void); void check_interface(void); void set_ifname(char **); void set_ifmtu(int); void set_ifv4addr(char **); void set_ifeaddr(char **); void new_arp(void); void set_arpeaddr(char **); void set_arpv4addr(char **); void reset_send(void); void set_sendif(char **); void set_sendvia(char **); void set_defaultrouter(char **); void new_icmpheader(void); void set_icmpcode(int); void set_icmptype(int); void set_icmpcodetok(char **); void set_icmptypetok(char **); void set_icmpid(int); void set_icmpseq(int); void set_icmpotime(int); void set_icmprtime(int); void set_icmpttime(int); void set_icmpmtu(int); void set_redir(int, char **); void new_ipv4opt(void); void set_icmppprob(int); void add_ipopt(int, void *); void end_ipopt(void); void set_secclass(char **); void free_anipheader(void); void end_ipv4(void); void end_icmp(void); void end_udp(void); void end_tcp(void); void end_data(void); void yyerror(char *); void iplang(FILE *); int arp_getipv4(char *, char *); int yyparse(void); %} %union { char *str; int num; } %token IL_NUMBER %type number digits optnumber %token IL_TOKEN %type token optoken %token IL_HEXDIGIT IL_COLON IL_DOT IL_EOF IL_COMMENT %token IL_INTERFACE IL_IFNAME IL_MTU IL_EADDR %token IL_IPV4 IL_V4PROTO IL_V4SRC IL_V4DST IL_V4OFF IL_V4V IL_V4HL IL_V4TTL %token IL_V4TOS IL_V4SUM IL_V4LEN IL_V4OPT IL_V4ID %token IL_TCP IL_SPORT IL_DPORT IL_TCPFL IL_TCPSEQ IL_TCPACK IL_TCPOFF %token IL_TCPWIN IL_TCPSUM IL_TCPURP IL_TCPOPT IL_TCPO_NOP IL_TCPO_EOL %token IL_TCPO_MSS IL_TCPO_WSCALE IL_TCPO_TS %token IL_UDP IL_UDPLEN IL_UDPSUM %token IL_ICMP IL_ICMPTYPE IL_ICMPCODE %token IL_SEND IL_VIA %token IL_ARP %token IL_DEFROUTER %token IL_SUM IL_OFF IL_LEN IL_V4ADDR IL_OPT %token IL_DATA IL_DLEN IL_DVALUE IL_DFILE %token IL_IPO_NOP IL_IPO_RR IL_IPO_ZSU IL_IPO_MTUP IL_IPO_MTUR IL_IPO_EOL %token IL_IPO_TS IL_IPO_TR IL_IPO_SEC IL_IPO_LSRR IL_IPO_ESEC %token IL_IPO_SATID IL_IPO_SSRR IL_IPO_ADDEXT IL_IPO_VISA IL_IPO_IMITD %token IL_IPO_EIP IL_IPO_FINN IL_IPO_SECCLASS IL_IPO_CIPSO IL_IPO_ENCODE %token IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3 %token IL_IPS_CONFID IL_IPS_UNCLASS IL_IPS_RESERV2 IL_IPS_RESERV1 %token IL_ICMP_ECHOREPLY IL_ICMP_UNREACH IL_ICMP_UNREACH_NET %token IL_ICMP_UNREACH_HOST IL_ICMP_UNREACH_PROTOCOL IL_ICMP_UNREACH_PORT %token IL_ICMP_UNREACH_NEEDFRAG IL_ICMP_UNREACH_SRCFAIL %token IL_ICMP_UNREACH_NET_UNKNOWN IL_ICMP_UNREACH_HOST_UNKNOWN %token IL_ICMP_UNREACH_ISOLATED IL_ICMP_UNREACH_NET_PROHIB %token IL_ICMP_UNREACH_HOST_PROHIB IL_ICMP_UNREACH_TOSNET %token IL_ICMP_UNREACH_TOSHOST IL_ICMP_UNREACH_FILTER_PROHIB %token IL_ICMP_UNREACH_HOST_PRECEDENCE IL_ICMP_UNREACH_PRECEDENCE_CUTOFF %token IL_ICMP_SOURCEQUENCH IL_ICMP_REDIRECT IL_ICMP_REDIRECT_NET %token IL_ICMP_REDIRECT_HOST IL_ICMP_REDIRECT_TOSNET %token IL_ICMP_REDIRECT_TOSHOST IL_ICMP_ECHO IL_ICMP_ROUTERADVERT %token IL_ICMP_ROUTERSOLICIT IL_ICMP_TIMXCEED IL_ICMP_TIMXCEED_INTRANS %token IL_ICMP_TIMXCEED_REASS IL_ICMP_PARAMPROB IL_ICMP_PARAMPROB_OPTABSENT %token IL_ICMP_TSTAMP IL_ICMP_TSTAMPREPLY IL_ICMP_IREQ IL_ICMP_IREQREPLY %token IL_ICMP_MASKREQ IL_ICMP_MASKREPLY IL_ICMP_SEQ IL_ICMP_ID %token IL_ICMP_OTIME IL_ICMP_RTIME IL_ICMP_TTIME %% file: line | line file | IL_COMMENT | IL_COMMENT file ; line: iface | arp | send | defrouter | ipline ; iface: ifhdr '{' ifaceopts '}' ';' { check_interface(); } ; ifhdr: IL_INTERFACE { new_interface(); } ; ifaceopts: ifaceopt | ifaceopt ifaceopts ; ifaceopt: IL_IFNAME token { set_ifname(&$2); } | IL_MTU number { set_ifmtu($2); } | IL_V4ADDR token { set_ifv4addr(&$2); } | IL_EADDR token { set_ifeaddr(&$2); } ; send: sendhdr '{' sendbody '}' ';' { packet_done(); } | sendhdr ';' { packet_done(); } ; sendhdr: IL_SEND { reset_send(); } ; sendbody: sendopt | sendbody sendopt ; sendopt: IL_IFNAME token { set_sendif(&$2); } | IL_VIA token { set_sendvia(&$2); } ; arp: arphdr '{' arpbody '}' ';' ; arphdr: IL_ARP { new_arp(); } ; arpbody: arpopt | arpbody arpopt ; arpopt: IL_V4ADDR token { set_arpv4addr(&$2); } | IL_EADDR token { set_arpeaddr(&$2); } ; defrouter: IL_DEFROUTER token { set_defaultrouter(&$2); } ; bodyline: ipline | tcp tcpline | udp udpline | icmp icmpline | data dataline ; ipline: ipv4 '{' ipv4body '}' ';' { end_ipv4(); } ; ipv4: IL_IPV4 { new_packet(); } ipv4body: ipv4type | ipv4type ipv4body | bodyline ; ipv4type: IL_V4PROTO token { set_ipv4proto(&$2); } | IL_V4SRC token { set_ipv4src(&$2); } | IL_V4DST token { set_ipv4dst(&$2); } | IL_V4OFF token { set_ipv4off(&$2); } | IL_V4V token { set_ipv4v(&$2); } | IL_V4HL token { set_ipv4hl(&$2); } | IL_V4ID token { set_ipv4id(&$2); } | IL_V4TTL token { set_ipv4ttl(&$2); } | IL_V4TOS token { set_ipv4tos(&$2); } | IL_V4SUM token { set_ipv4sum(&$2); } | IL_V4LEN token { set_ipv4len(&$2); } | ipv4opt '{' ipv4optlist '}' ';' { end_ipopt(); } ; tcp: IL_TCP { new_tcpheader(); } ; tcpline: '{' tcpheader '}' ';' { end_tcp(); } ; tcpheader: tcpbody | tcpbody tcpheader | bodyline ; tcpbody: IL_SPORT token { set_tcpsport(&$2); } | IL_DPORT token { set_tcpdport(&$2); } | IL_TCPSEQ token { set_tcpseq(&$2); } | IL_TCPACK token { set_tcpack(&$2); } | IL_TCPOFF token { set_tcpoff(&$2); } | IL_TCPURP token { set_tcpurp(&$2); } | IL_TCPWIN token { set_tcpwin(&$2); } | IL_TCPSUM token { set_tcpsum(&$2); } | IL_TCPFL token { set_tcpflags(&$2); } | IL_TCPOPT '{' tcpopts '}' ';' { end_tcpopt(); } ; tcpopts: | tcpopt tcpopts ; tcpopt: IL_TCPO_NOP ';' { set_tcpopt(IL_TCPO_NOP, NULL); } | IL_TCPO_EOL ';' { set_tcpopt(IL_TCPO_EOL, NULL); } | IL_TCPO_MSS optoken { set_tcpopt(IL_TCPO_MSS,&$2);} | IL_TCPO_WSCALE optoken { set_tcpopt(IL_TCPO_WSCALE,&$2);} | IL_TCPO_TS optoken { set_tcpopt(IL_TCPO_TS, &$2);} ; udp: IL_UDP { new_udpheader(); } ; udpline: '{' udpheader '}' ';' { end_udp(); } ; udpheader: udpbody | udpbody udpheader | bodyline ; udpbody: IL_SPORT token { set_tcpsport(&$2); } | IL_DPORT token { set_tcpdport(&$2); } | IL_UDPLEN token { set_udplen(&$2); } | IL_UDPSUM token { set_udpsum(&$2); } ; icmp: IL_ICMP { new_icmpheader(); } ; icmpline: '{' icmpbody '}' ';' { end_icmp(); } ; icmpbody: icmpheader | icmpheader bodyline ; icmpheader: IL_ICMPTYPE icmptype | IL_ICMPTYPE icmptype icmpcode ; icmpcode: IL_ICMPCODE token { set_icmpcodetok(&$2); } ; icmptype: IL_ICMP_ECHOREPLY ';' { set_icmptype(ICMP_ECHOREPLY); } | IL_ICMP_ECHOREPLY '{' icmpechoopts '}' ';' | unreach | IL_ICMP_SOURCEQUENCH ';' { set_icmptype(ICMP_SOURCEQUENCH); } | redirect | IL_ICMP_ROUTERADVERT ';' { set_icmptype(ICMP_ROUTERADVERT); } | IL_ICMP_ROUTERSOLICIT ';' { set_icmptype(ICMP_ROUTERSOLICIT); } | IL_ICMP_ECHO ';' { set_icmptype(ICMP_ECHO); } | IL_ICMP_ECHO '{' icmpechoopts '}' ';' | IL_ICMP_TIMXCEED ';' { set_icmptype(ICMP_TIMXCEED); } | IL_ICMP_TIMXCEED '{' exceed '}' ';' | IL_ICMP_TSTAMP ';' { set_icmptype(ICMP_TSTAMP); } | IL_ICMP_TSTAMPREPLY ';' { set_icmptype(ICMP_TSTAMPREPLY); } | IL_ICMP_TSTAMPREPLY '{' icmptsopts '}' ';' | IL_ICMP_IREQ ';' { set_icmptype(ICMP_IREQ); } | IL_ICMP_IREQREPLY ';' { set_icmptype(ICMP_IREQREPLY); } | IL_ICMP_IREQREPLY '{' data dataline '}' ';' | IL_ICMP_MASKREQ ';' { set_icmptype(ICMP_MASKREQ); } | IL_ICMP_MASKREPLY ';' { set_icmptype(ICMP_MASKREPLY); } | IL_ICMP_MASKREPLY '{' token '}' ';' | IL_ICMP_PARAMPROB ';' { set_icmptype(ICMP_PARAMPROB); } | IL_ICMP_PARAMPROB '{' paramprob '}' ';' | IL_TOKEN ';' { set_icmptypetok(&$1); } ; icmpechoopts: | icmpechoopts icmpecho ; icmpecho: IL_ICMP_SEQ number { set_icmpseq($2); } | IL_ICMP_ID number { set_icmpid($2); } ; icmptsopts: | icmptsopts icmpts ';' ; icmpts: IL_ICMP_OTIME number { set_icmpotime($2); } | IL_ICMP_RTIME number { set_icmprtime($2); } | IL_ICMP_TTIME number { set_icmpttime($2); } ; unreach: IL_ICMP_UNREACH | IL_ICMP_UNREACH '{' unreachopts '}' ';' ; unreachopts: IL_ICMP_UNREACH_NET line | IL_ICMP_UNREACH_HOST line | IL_ICMP_UNREACH_PROTOCOL line | IL_ICMP_UNREACH_PORT line | IL_ICMP_UNREACH_NEEDFRAG number ';' { set_icmpmtu($2); } | IL_ICMP_UNREACH_SRCFAIL line | IL_ICMP_UNREACH_NET_UNKNOWN line | IL_ICMP_UNREACH_HOST_UNKNOWN line | IL_ICMP_UNREACH_ISOLATED line | IL_ICMP_UNREACH_NET_PROHIB line | IL_ICMP_UNREACH_HOST_PROHIB line | IL_ICMP_UNREACH_TOSNET line | IL_ICMP_UNREACH_TOSHOST line | IL_ICMP_UNREACH_FILTER_PROHIB line | IL_ICMP_UNREACH_HOST_PRECEDENCE line | IL_ICMP_UNREACH_PRECEDENCE_CUTOFF line ; redirect: IL_ICMP_REDIRECT | IL_ICMP_REDIRECT '{' redirectopts '}' ';' ; redirectopts: | IL_ICMP_REDIRECT_NET token { set_redir(0, &$2); } | IL_ICMP_REDIRECT_HOST token { set_redir(1, &$2); } | IL_ICMP_REDIRECT_TOSNET token { set_redir(2, &$2); } | IL_ICMP_REDIRECT_TOSHOST token { set_redir(3, &$2); } ; exceed: IL_ICMP_TIMXCEED_INTRANS line | IL_ICMP_TIMXCEED_REASS line ; paramprob: IL_ICMP_PARAMPROB_OPTABSENT | IL_ICMP_PARAMPROB_OPTABSENT paraprobarg paraprobarg: '{' number '}' ';' { set_icmppprob($2); } ; ipv4opt: IL_V4OPT { new_ipv4opt(); } ; ipv4optlist: | ipv4opts ipv4optlist ; ipv4opts: IL_IPO_NOP ';' { add_ipopt(IL_IPO_NOP, NULL); } | IL_IPO_RR optnumber { add_ipopt(IL_IPO_RR, &$2); } | IL_IPO_ZSU ';' { add_ipopt(IL_IPO_ZSU, NULL); } | IL_IPO_MTUP ';' { add_ipopt(IL_IPO_MTUP, NULL); } | IL_IPO_MTUR ';' { add_ipopt(IL_IPO_MTUR, NULL); } | IL_IPO_ENCODE ';' { add_ipopt(IL_IPO_ENCODE, NULL); } | IL_IPO_TS ';' { add_ipopt(IL_IPO_TS, NULL); } | IL_IPO_TR ';' { add_ipopt(IL_IPO_TR, NULL); } | IL_IPO_SEC ';' { add_ipopt(IL_IPO_SEC, NULL); } | IL_IPO_SECCLASS secclass { add_ipopt(IL_IPO_SECCLASS, sclass); } | IL_IPO_LSRR token { add_ipopt(IL_IPO_LSRR,&$2); } | IL_IPO_ESEC ';' { add_ipopt(IL_IPO_ESEC, NULL); } | IL_IPO_CIPSO ';' { add_ipopt(IL_IPO_CIPSO, NULL); } | IL_IPO_SATID optnumber { add_ipopt(IL_IPO_SATID,&$2);} | IL_IPO_SSRR token { add_ipopt(IL_IPO_SSRR,&$2); } | IL_IPO_ADDEXT ';' { add_ipopt(IL_IPO_ADDEXT, NULL); } | IL_IPO_VISA ';' { add_ipopt(IL_IPO_VISA, NULL); } | IL_IPO_IMITD ';' { add_ipopt(IL_IPO_IMITD, NULL); } | IL_IPO_EIP ';' { add_ipopt(IL_IPO_EIP, NULL); } | IL_IPO_FINN ';' { add_ipopt(IL_IPO_FINN, NULL); } ; secclass: IL_IPS_RESERV4 ';' { set_secclass(&$1); } | IL_IPS_TOPSECRET ';' { set_secclass(&$1); } | IL_IPS_SECRET ';' { set_secclass(&$1); } | IL_IPS_RESERV3 ';' { set_secclass(&$1); } | IL_IPS_CONFID ';' { set_secclass(&$1); } | IL_IPS_UNCLASS ';' { set_secclass(&$1); } | IL_IPS_RESERV2 ';' { set_secclass(&$1); } | IL_IPS_RESERV1 ';' { set_secclass(&$1); } ; data: IL_DATA { new_data(); } ; dataline: '{' databody '}' ';' { end_data(); } ; databody: dataopts | dataopts databody ; dataopts: IL_DLEN token { set_datalen(&$2); } | IL_DVALUE token { set_data(&$2); } | IL_DFILE token { set_datafile(&$2); } ; token: IL_TOKEN ';' ; optoken: ';' { $$ = ""; } | token ; number: digits ';' ; optnumber: ';' { $$ = 0; } | number ; digits: IL_NUMBER | digits IL_NUMBER ; %% struct statetoopt toipopts[] = { { IL_IPO_NOP, IPOPT_NOP }, { IL_IPO_RR, IPOPT_RR }, { IL_IPO_ZSU, IPOPT_ZSU }, { IL_IPO_MTUP, IPOPT_MTUP }, { IL_IPO_MTUR, IPOPT_MTUR }, { IL_IPO_ENCODE, IPOPT_ENCODE }, { IL_IPO_TS, IPOPT_TS }, { IL_IPO_TR, IPOPT_TR }, { IL_IPO_SEC, IPOPT_SECURITY }, { IL_IPO_SECCLASS, IPOPT_SECURITY }, { IL_IPO_LSRR, IPOPT_LSRR }, { IL_IPO_ESEC, IPOPT_E_SEC }, { IL_IPO_CIPSO, IPOPT_CIPSO }, { IL_IPO_SATID, IPOPT_SATID }, { IL_IPO_SSRR, IPOPT_SSRR }, { IL_IPO_ADDEXT, IPOPT_ADDEXT }, { IL_IPO_VISA, IPOPT_VISA }, { IL_IPO_IMITD, IPOPT_IMITD }, { IL_IPO_EIP, IPOPT_EIP }, { IL_IPO_FINN, IPOPT_FINN }, { 0, 0 } }; struct statetoopt tosecopts[] = { { IL_IPS_RESERV4, IPSO_CLASS_RES4 }, { IL_IPS_TOPSECRET, IPSO_CLASS_TOPS }, { IL_IPS_SECRET, IPSO_CLASS_SECR }, { IL_IPS_RESERV3, IPSO_CLASS_RES3 }, { IL_IPS_CONFID, IPSO_CLASS_CONF }, { IL_IPS_UNCLASS, IPSO_CLASS_UNCL }, { IL_IPS_RESERV2, IPSO_CLASS_RES2 }, { IL_IPS_RESERV1, IPSO_CLASS_RES1 }, { 0, 0 } }; struct in_addr getipv4addr(arg) char *arg; { struct hostent *hp; struct in_addr in; in.s_addr = 0xffffffff; if ((hp = gethostbyname(arg))) bcopy(hp->h_addr, &in.s_addr, sizeof(struct in_addr)); else in.s_addr = inet_addr(arg); - return in; + return(in); } u_short getportnum(pr, name) char *pr, *name; { struct servent *sp; if (!(sp = getservbyname(name, pr))) - return htons(atoi(name)); - return sp->s_port; + return(htons(atoi(name))); + return(sp->s_port); } struct ether_addr *geteaddr(char *arg, struct ether_addr *buf) { struct ether_addr *e; e = ether_aton(arg); if (!e) fprintf(stderr, "Invalid ethernet address: %s\n", arg); else # ifdef __FreeBSD__ bcopy(e->octet, buf->octet, sizeof(e->octet)); # else bcopy(e->ether_addr_octet, buf->ether_addr_octet, sizeof(e->ether_addr_octet)); # endif - return e; + return(e); } void *new_header(int type) { aniphdr_t *aip, *oip = canip; int sz = 0; aip = (aniphdr_t *)calloc(1, sizeof(*aip)); *aniptail = aip; aniptail = &aip->ah_next; aip->ah_p = type; aip->ah_prev = oip; canip = aip; if (type == IPPROTO_UDP) sz = sizeof(udphdr_t); else if (type == IPPROTO_TCP) sz = sizeof(tcphdr_t); else if (type == IPPROTO_ICMP) sz = sizeof(icmphdr_t); else if (type == IPPROTO_IP) sz = sizeof(ip_t); if (oip) canip->ah_data = oip->ah_data + oip->ah_len; else canip->ah_data = (char *)ipbuffer; /* * Increase the size fields in all wrapping headers. */ for (aip = aniphead; aip; aip = aip->ah_next) { aip->ah_len += sz; if (aip->ah_p == IPPROTO_IP) aip->ah_ip->ip_len += sz; else if (aip->ah_p == IPPROTO_UDP) aip->ah_udp->uh_ulen += sz; } - return (void *)canip->ah_data; + return(void *)canip->ah_data; } void free_aniplist(void) { aniphdr_t *aip, **aipp = &aniphead; while ((aip = *aipp)) { *aipp = aip->ah_next; free(aip); } aniptail = &aniphead; } void inc_anipheaders(int inc) { aniphdr_t *aip; for (aip = aniphead; aip; aip = aip->ah_next) { aip->ah_len += inc; if (aip->ah_p == IPPROTO_IP) aip->ah_ip->ip_len += inc; else if (aip->ah_p == IPPROTO_UDP) aip->ah_udp->uh_ulen += inc; } } void new_data(void) { (void) new_header(-1); canip->ah_len = 0; } void set_datalen(char **arg) { int len; len = strtol(*arg, NULL, 0); inc_anipheaders(len); free(*arg); *arg = NULL; } void set_data(char **arg) { u_char *s = (u_char *)*arg, *t = (u_char *)canip->ah_data, c; int len = 0, todo = 0, quote = 0, val = 0; while ((c = *s++)) { if (todo) { if (ISDIGIT(c)) { todo--; if (c > '7') { fprintf(stderr, "octal with %c!\n", c); break; } val <<= 3; val |= (c - '0'); } if (!ISDIGIT(c) || !todo) { *t++ = (u_char)(val & 0xff); todo = 0; } if (todo) continue; } if (quote) { if (ISDIGIT(c)) { todo = 2; if (c > '7') { fprintf(stderr, "octal with %c!\n", c); break; } val = (c - '0'); } else { switch (c) { case '\"' : *t++ = '\"'; break; case '\\' : *t++ = '\\'; break; case 'n' : *t++ = '\n'; break; case 'r' : *t++ = '\r'; break; case 't' : *t++ = '\t'; break; } } quote = 0; continue; } if (c == '\\') quote = 1; else *t++ = c; } if (todo) *t++ = (u_char)(val & 0xff); if (quote) *t++ = '\\'; len = t - (u_char *)canip->ah_data; inc_anipheaders(len - canip->ah_len); canip->ah_len = len; } void set_datafile(char **arg) { struct stat sb; char *file = *arg; int fd, len; if ((fd = open(file, O_RDONLY)) == -1) { perror("open"); exit(-1); } if (fstat(fd, &sb) == -1) { perror("fstat"); exit(-1); } if ((sb.st_size + aniphead->ah_len ) > 65535) { fprintf(stderr, "data file %s too big to include.\n", file); close(fd); return; } if ((len = read(fd, canip->ah_data, sb.st_size)) == -1) { perror("read"); close(fd); return; } inc_anipheaders(len); canip->ah_len += len; close(fd); } void new_packet(void) { static u_short id = 0; if (!aniphead) bzero((char *)ipbuffer, sizeof(ipbuffer)); ip = (ip_t *)new_header(IPPROTO_IP); ip->ip_v = IPVERSION; ip->ip_hl = sizeof(ip_t) >> 2; ip->ip_len = sizeof(ip_t); ip->ip_ttl = 63; ip->ip_id = htons(id++); } void set_ipv4proto(arg) char **arg; { struct protoent *pr; if ((pr = getprotobyname(*arg))) ip->ip_p = pr->p_proto; else if (!(ip->ip_p = atoi(*arg))) fprintf(stderr, "unknown protocol %s\n", *arg); free(*arg); *arg = NULL; } void set_ipv4src(char **arg) { ip->ip_src = getipv4addr(*arg); free(*arg); *arg = NULL; } void set_ipv4dst(char **arg) { ip->ip_dst = getipv4addr(*arg); free(*arg); *arg = NULL; } void set_ipv4off(char **arg) { ip->ip_off = htons(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_ipv4v(char **arg) { ip->ip_v = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void set_ipv4hl(char **arg) { int newhl, inc; newhl = strtol(*arg, NULL, 0); inc = (newhl - ip->ip_hl) << 2; ip->ip_len += inc; ip->ip_hl = newhl; canip->ah_len += inc; free(*arg); *arg = NULL; } void set_ipv4ttl(char **arg) { ip->ip_ttl = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void set_ipv4tos(char **arg) { ip->ip_tos = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void set_ipv4id(char **arg) { ip->ip_id = htons(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_ipv4sum(char **arg) { ip->ip_sum = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void set_ipv4len(char **arg) { int len; len = strtol(*arg, NULL, 0); inc_anipheaders(len - ip->ip_len); ip->ip_len = len; free(*arg); *arg = NULL; } void new_tcpheader(void) { if ((ip->ip_p) && (ip->ip_p != IPPROTO_TCP)) { fprintf(stderr, "protocol %d specified with TCP!\n", ip->ip_p); return; } ip->ip_p = IPPROTO_TCP; tcp = (tcphdr_t *)new_header(IPPROTO_TCP); tcp->th_win = htons(4096); tcp->th_off = sizeof(*tcp) >> 2; } void set_tcpsport(char **arg) { u_short *port; char *pr; if (ip->ip_p == IPPROTO_UDP) { port = &udp->uh_sport; pr = "udp"; } else { port = &tcp->th_sport; pr = "udp"; } *port = getportnum(pr, *arg); free(*arg); *arg = NULL; } void set_tcpdport(char **arg) { u_short *port; char *pr; if (ip->ip_p == IPPROTO_UDP) { port = &udp->uh_dport; pr = "udp"; } else { port = &tcp->th_dport; pr = "udp"; } *port = getportnum(pr, *arg); free(*arg); *arg = NULL; } void set_tcpseq(char **arg) { tcp->th_seq = htonl(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_tcpack(char **arg) { tcp->th_ack = htonl(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_tcpoff(char **arg) { int off; off = strtol(*arg, NULL, 0); inc_anipheaders((off - tcp->th_off) << 2); tcp->th_off = off; free(*arg); *arg = NULL; } void set_tcpurp(char **arg) { tcp->th_urp = htons(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_tcpwin(char **arg) { tcp->th_win = htons(strtol(*arg, NULL, 0)); free(*arg); *arg = NULL; } void set_tcpsum(char **arg) { tcp->th_sum = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void set_tcpflags(char **arg) { static char flags[] = "ASURPF"; static int flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH, TH_FIN } ; char *s, *t; for (s = *arg; *s; s++) if (!(t = strchr(flags, *s))) { if (s - *arg) { fprintf(stderr, "unknown TCP flag %c\n", *s); break; } tcp->th_flags = strtol(*arg, NULL, 0); break; } else tcp->th_flags |= flagv[t - flags]; free(*arg); *arg = NULL; } void set_tcpopt(int state, char **arg) { u_char *s; int val, len, val2, pad, optval; if (arg && *arg) val = atoi(*arg); else val = 0; s = (u_char *)tcp + sizeof(*tcp) + canip->ah_optlen; switch (state) { case IL_TCPO_EOL : optval = 0; len = 1; break; case IL_TCPO_NOP : optval = 1; len = 1; break; case IL_TCPO_MSS : optval = 2; len = 4; break; case IL_TCPO_WSCALE : optval = 3; len = 3; break; case IL_TCPO_TS : optval = 8; len = 10; break; default : optval = 0; len = 0; break; } if (len > 1) { /* * prepend padding - if required. */ if (len & 3) for (pad = 4 - (len & 3); pad; pad--) { *s++ = 1; canip->ah_optlen++; } /* * build tcp option */ *s++ = (u_char)optval; *s++ = (u_char)len; if (len > 2) { if (len == 3) { /* 1 byte - char */ *s++ = (u_char)val; } else if (len == 4) { /* 2 bytes - short */ *s++ = (u_char)((val >> 8) & 0xff); *s++ = (u_char)(val & 0xff); } else if (len >= 6) { /* 4 bytes - long */ val2 = htonl(val); bcopy((char *)&val2, s, 4); } s += (len - 2); } } else *s++ = (u_char)optval; canip->ah_lastopt = optval; canip->ah_optlen += len; if (arg && *arg) { free(*arg); *arg = NULL; } } void end_tcpopt(void) { int pad; char *s = (char *)tcp; s += sizeof(*tcp) + canip->ah_optlen; /* * pad out so that we have a multiple of 4 bytes in size fo the * options. make sure last byte is EOL. */ if (canip->ah_optlen & 3) { if (canip->ah_lastopt != 1) { for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) { *s++ = 1; canip->ah_optlen++; } canip->ah_optlen++; } else { s -= 1; for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) { *s++ = 1; canip->ah_optlen++; } } *s++ = 0; } tcp->th_off = (sizeof(*tcp) + canip->ah_optlen) >> 2; inc_anipheaders(canip->ah_optlen); } void new_udpheader(void) { if ((ip->ip_p) && (ip->ip_p != IPPROTO_UDP)) { fprintf(stderr, "protocol %d specified with UDP!\n", ip->ip_p); return; } ip->ip_p = IPPROTO_UDP; udp = (udphdr_t *)new_header(IPPROTO_UDP); udp->uh_ulen = sizeof(*udp); } void set_udplen(arg) char **arg; { int len; len = strtol(*arg, NULL, 0); inc_anipheaders(len - udp->uh_ulen); udp->uh_ulen = len; free(*arg); *arg = NULL; } void set_udpsum(char **arg) { udp->uh_sum = strtol(*arg, NULL, 0); free(*arg); *arg = NULL; } void prep_packet(void) { iface_t *ifp; struct in_addr gwip; ifp = sending.snd_if; if (!ifp) { fprintf(stderr, "no interface defined for sending!\n"); return; } if (ifp->if_fd == -1) ifp->if_fd = initdevice(ifp->if_name, 5); gwip = sending.snd_gw; if (!gwip.s_addr) { if (aniphead == NULL) { fprintf(stderr, "no destination address defined for sending\n"); return; } gwip = aniphead->ah_ip->ip_dst; } (void) send_ip(ifp->if_fd, ifp->if_MTU, (ip_t *)ipbuffer, gwip, 2); } void packet_done(void) { char outline[80]; int i, j, k; u_char *s = (u_char *)ipbuffer, *t = (u_char *)outline; if (opts & OPT_VERBOSE) { ip->ip_len = htons(ip->ip_len); for (i = ntohs(ip->ip_len), j = 0; i; i--, j++, s++) { if (j && !(j & 0xf)) { *t++ = '\n'; *t = '\0'; fputs(outline, stdout); fflush(stdout); t = (u_char *)outline; *t = '\0'; } sprintf((char *)t, "%02x", *s & 0xff); t += 2; if (!((j + 1) & 0xf)) { s -= 15; sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); s--; } if ((j + 1) & 0xf) *t++ = ' ';; } if (j & 0xf) { for (k = 16 - (j & 0xf); k; k--) { *t++ = ' '; *t++ = ' '; *t++ = ' '; } sprintf((char *)t, " "); t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } fputs(outline, stdout); fflush(stdout); ip->ip_len = ntohs(ip->ip_len); } prep_packet(); free_aniplist(); } void new_interface(void) { cifp = (iface_t *)calloc(1, sizeof(iface_t)); *iftail = cifp; iftail = &cifp->if_next; cifp->if_fd = -1; } void check_interface(void) { if (!cifp->if_name || !*cifp->if_name) fprintf(stderr, "No interface name given!\n"); if (!cifp->if_MTU || !*cifp->if_name) fprintf(stderr, "Interface %s has an MTU of 0!\n", cifp->if_name); } void set_ifname(char **arg) { cifp->if_name = *arg; *arg = NULL; } void set_ifmtu(int arg) { cifp->if_MTU = arg; } void set_ifv4addr(char **arg) { cifp->if_addr = getipv4addr(*arg); free(*arg); *arg = NULL; } void set_ifeaddr(char **arg) { (void) geteaddr(*arg, &cifp->if_eaddr); free(*arg); *arg = NULL; } void new_arp(void) { carp = (arp_t *)calloc(1, sizeof(arp_t)); *arptail = carp; arptail = &carp->arp_next; } void set_arpeaddr(char **arg) { (void) geteaddr(*arg, &carp->arp_eaddr); free(*arg); *arg = NULL; } void set_arpv4addr(char **arg) { carp->arp_addr = getipv4addr(*arg); free(*arg); *arg = NULL; } int arp_getipv4(char *ip, char *addr) { arp_t *a; for (a = arplist; a; a = a->arp_next) if (!bcmp(ip, (char *)&a->arp_addr, 4)) { bcopy((char *)&a->arp_eaddr, addr, 6); - return 0; + return(0); } - return -1; + return(-1); } void reset_send(void) { sending.snd_if = iflist; sending.snd_gw = defrouter; } void set_sendif(char **arg) { iface_t *ifp; for (ifp = iflist; ifp; ifp = ifp->if_next) if (ifp->if_name && !strcmp(ifp->if_name, *arg)) break; sending.snd_if = ifp; if (!ifp) fprintf(stderr, "couldn't find interface %s\n", *arg); free(*arg); *arg = NULL; } void set_sendvia(char **arg) { sending.snd_gw = getipv4addr(*arg); free(*arg); *arg = NULL; } void set_defaultrouter(char **arg) { defrouter = getipv4addr(*arg); free(*arg); *arg = NULL; } void new_icmpheader(void) { if ((ip->ip_p) && (ip->ip_p != IPPROTO_ICMP)) { fprintf(stderr, "protocol %d specified with ICMP!\n", ip->ip_p); return; } ip->ip_p = IPPROTO_ICMP; icmp = (icmphdr_t *)new_header(IPPROTO_ICMP); } void set_icmpcode(int code) { icmp->icmp_code = code; } void set_icmptype(int type) { icmp->icmp_type = type; } void set_icmpcodetok(char **code) { char *s; int i; for (i = 0; (s = icmpcodes[i]); i++) if (!strcmp(s, *code)) { icmp->icmp_code = i; break; } if (!s) fprintf(stderr, "unknown ICMP code %s\n", *code); free(*code); *code = NULL; } void set_icmptypetok(char **type) { char *s; int i, done = 0; for (i = 0; !(s = icmptypes[i]) || strcmp(s, "END"); i++) if (s && !strcmp(s, *type)) { icmp->icmp_type = i; done = 1; break; } if (!done) fprintf(stderr, "unknown ICMP type %s\n", *type); free(*type); *type = NULL; } void set_icmpid(int arg) { icmp->icmp_id = htons(arg); } void set_icmpseq(int arg) { icmp->icmp_seq = htons(arg); } void set_icmpotime(int arg) { icmp->icmp_otime = htonl(arg); } void set_icmprtime(int arg) { icmp->icmp_rtime = htonl(arg); } void set_icmpttime(int arg) { icmp->icmp_ttime = htonl(arg); } void set_icmpmtu(int arg) { icmp->icmp_nextmtu = htons(arg); } void set_redir(int redir, char **arg) { icmp->icmp_code = redir; icmp->icmp_gwaddr = getipv4addr(*arg); free(*arg); *arg = NULL; } void set_icmppprob(int num) { icmp->icmp_pptr = num; } void new_ipv4opt(void) { new_header(-2); } void add_ipopt(int state, void *ptr) { struct ipopt_names *io; struct statetoopt *sto; char numbuf[16], *arg, **param = ptr; int inc, hlen; if (state == IL_IPO_RR || state == IL_IPO_SATID) { if (param) snprintf(numbuf, sizeof(numbuf), "%d", *(int *)param); else strcpy(numbuf, "0"); arg = numbuf; } else arg = param ? *param : NULL; if (canip->ah_next) { fprintf(stderr, "cannot specify options after data body\n"); return; } for (sto = toipopts; sto->sto_st; sto++) if (sto->sto_st == state) break; if (!sto->sto_st) { fprintf(stderr, "No mapping for state %d to IP option\n", state); return; } hlen = sizeof(ip_t) + canip->ah_optlen; for (io = ionames; io->on_name; io++) if (io->on_value == sto->sto_op) break; canip->ah_lastopt = io->on_value; if (io->on_name) { inc = addipopt((char *)ip + hlen, io, hlen - sizeof(ip_t),arg); if (inc > 0) { while (inc & 3) { ((char *)ip)[sizeof(*ip) + inc] = IPOPT_NOP; canip->ah_lastopt = IPOPT_NOP; inc++; } hlen += inc; } } canip->ah_optlen = hlen - sizeof(ip_t); if (state != IL_IPO_RR && state != IL_IPO_SATID) if (param && *param) { free(*param); *param = NULL; } sclass = NULL; } void end_ipopt(void) { int pad; char *s, *buf = (char *)ip; /* * pad out so that we have a multiple of 4 bytes in size fo the * options. make sure last byte is EOL. */ if (canip->ah_lastopt == IPOPT_NOP) { buf[sizeof(*ip) + canip->ah_optlen - 1] = IPOPT_EOL; } else if (canip->ah_lastopt != IPOPT_EOL) { s = buf + sizeof(*ip) + canip->ah_optlen; for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) { *s++ = IPOPT_NOP; *s = IPOPT_EOL; canip->ah_optlen++; } canip->ah_optlen++; } else { s = buf + sizeof(*ip) + canip->ah_optlen - 1; for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) { *s++ = IPOPT_NOP; *s = IPOPT_EOL; canip->ah_optlen++; } } ip->ip_hl = (sizeof(*ip) + canip->ah_optlen) >> 2; inc_anipheaders(canip->ah_optlen); free_anipheader(); } void set_secclass(char **arg) { sclass = *arg; *arg = NULL; } void free_anipheader(void) { aniphdr_t *aip; aip = canip; if ((canip = aip->ah_prev)) { canip->ah_next = NULL; aniptail = &canip->ah_next; } if (canip) free(aip); } void end_ipv4(void) { aniphdr_t *aip; ip->ip_sum = 0; ip->ip_len = htons(ip->ip_len); ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2); ip->ip_len = ntohs(ip->ip_len); free_anipheader(); for (aip = aniphead, ip = NULL; aip; aip = aip->ah_next) if (aip->ah_p == IPPROTO_IP) ip = aip->ah_ip; } void end_icmp(void) { aniphdr_t *aip; icmp->icmp_cksum = 0; icmp->icmp_cksum = chksum((u_short *)icmp, canip->ah_len); free_anipheader(); for (aip = aniphead, icmp = NULL; aip; aip = aip->ah_next) if (aip->ah_p == IPPROTO_ICMP) icmp = aip->ah_icmp; } void end_udp(void) { u_long sum; aniphdr_t *aip; ip_t iptmp; bzero((char *)&iptmp, sizeof(iptmp)); iptmp.ip_p = ip->ip_p; iptmp.ip_src = ip->ip_src; iptmp.ip_dst = ip->ip_dst; iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2)); sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp)); udp->uh_ulen = htons(udp->uh_ulen); udp->uh_sum = c_chksum((u_short *)udp, (u_int)ntohs(iptmp.ip_len), sum); free_anipheader(); for (aip = aniphead, udp = NULL; aip; aip = aip->ah_next) if (aip->ah_p == IPPROTO_UDP) udp = aip->ah_udp; } void end_tcp(void) { u_long sum; aniphdr_t *aip; ip_t iptmp; bzero((char *)&iptmp, sizeof(iptmp)); iptmp.ip_p = ip->ip_p; iptmp.ip_src = ip->ip_src; iptmp.ip_dst = ip->ip_dst; iptmp.ip_len = htons(ip->ip_len - (ip->ip_hl << 2)); sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp)); tcp->th_sum = 0; tcp->th_sum = c_chksum((u_short *)tcp, (u_int)ntohs(iptmp.ip_len), sum); free_anipheader(); for (aip = aniphead, tcp = NULL; aip; aip = aip->ah_next) if (aip->ah_p == IPPROTO_TCP) tcp = aip->ah_tcp; } void end_data(void) { free_anipheader(); } void iplang(FILE *fp) { yyin = fp; yydebug = (opts & OPT_DEBUG) ? 1 : 0; while (!feof(fp)) yyparse(); } u_short c_chksum(u_short *buf, u_int len, u_long init) { u_long sum = init; int nwords = len >> 1; for(; nwords > 0; nwords--) sum += *buf++; sum = (sum>>16) + (sum & 0xffff); sum += (sum >>16); - return (~sum); + return(~sum); } u_long p_chksum(u_short *buf, u_int len) { u_long sum = 0; int nwords = len >> 1; for(; nwords > 0; nwords--) sum += *buf++; - return sum; + return(sum); } diff --git a/sbin/ipf/ipmon/ipmon.c b/sbin/ipf/ipmon/ipmon.c index c5dd8828d6d2..f828a17fda41 100644 --- a/sbin/ipf/ipmon/ipmon.c +++ b/sbin/ipf/ipmon/ipmon.c @@ -1,1855 +1,1855 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" #include "ipmon.h" #include #include #include #include #include #include #if !defined(lint) static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #define STRERROR(x) strerror(x) 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; char *ist_name; } icmp_subtype_t; typedef struct icmp_type { int it_val; struct icmp_subtype *it_subtable; size_t it_stsize; char *it_name; } icmp_type_t; #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) struct flags tcpfl[] = { { TH_ACK, 'A' }, { TH_RST, 'R' }, { TH_SYN, 'S' }, { TH_FIN, 'F' }, { TH_URG, 'U' }, { TH_PUSH,'P' }, { TH_ECN, 'E' }, { TH_CWR, 'C' }, { 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", }; #if SOLARIS static char *pidfile = "/etc/opt/ipf/ipmon.pid"; #else static char *pidfile = "/var/run/ipmon.pid"; #endif static char line[2048]; static int donehup = 0; static void usage(char *); static void handlehup(int); static void flushlogs(char *, FILE *); static void print_log(config_t *, logsource_t *, char *, int); static void print_ipflog(config_t *, char *, int); static void print_natlog(config_t *, char *, int); static void print_statelog(config_t *, char *, int); static int read_log(int, int *, char *, int); static void write_pid(char *); static char *icmpname(u_int, u_int); static char *icmpname6(u_int, u_int); static icmp_type_t *find_icmptype(int, icmp_type_t *, size_t); static icmp_subtype_t *find_icmpsubtype(int, icmp_subtype_t *, size_t); static struct tm *get_tm(time_t); char *portlocalname(int, char *, u_int); int main(int, char *[]); static void logopts(int, char *); static void init_tabs(void); static char *getlocalproto(u_int); static void openlogs(config_t *conf); static int read_loginfo(config_t *conf); static void initconfig(config_t *conf); static char **protocols = NULL; static char **udp_ports = NULL; static char **tcp_ports = NULL; #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[] = { { ICMP_UNREACH_NET, "net" }, { ICMP_UNREACH_HOST, "host" }, { ICMP_UNREACH_PROTOCOL, "protocol" }, { ICMP_UNREACH_PORT, "port" }, { ICMP_UNREACH_NEEDFRAG, "needfrag" }, { ICMP_UNREACH_SRCFAIL, "srcfail" }, { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, { ICMP_UNREACH_NET, "isolated" }, { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, { ICMP_UNREACH_TOSNET, "tosnet" }, { ICMP_UNREACH_TOSHOST, "toshost" }, { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, { -2, NULL } }; static icmp_subtype_t redirectnames[] = { { ICMP_REDIRECT_NET, "net" }, { ICMP_REDIRECT_HOST, "host" }, { ICMP_REDIRECT_TOSNET, "tosnet" }, { ICMP_REDIRECT_TOSHOST, "toshost" }, { -2, NULL } }; static icmp_subtype_t timxceednames[] = { { ICMP_TIMXCEED_INTRANS, "transit" }, { ICMP_TIMXCEED_REASS, "reassem" }, { -2, NULL } }; static icmp_subtype_t paramnames[] = { { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, { ICMP_PARAMPROB_LENGTH, "length" }, { -2, NULL } }; static icmp_type_t icmptypes4[] = { { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, { -1, NULL, 0, NULL }, { -1, NULL, 0, NULL }, { ICMP_UNREACH, icmpunreachnames, IST_SZ(icmpunreachnames),"unreach" }, { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, { ICMP_REDIRECT, redirectnames, IST_SZ(redirectnames), "redirect" }, { -1, NULL, 0, NULL }, { -1, NULL, 0, NULL }, { ICMP_ECHO, NULL, 0, "echo" }, { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, { ICMP_TIMXCEED, timxceednames, IST_SZ(timxceednames), "timxceed" }, { ICMP_PARAMPROB, paramnames, IST_SZ(paramnames), "paramprob" }, { ICMP_TSTAMP, NULL, 0, "timestamp" }, { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, { ICMP_IREQ, NULL, 0, "inforeq" }, { ICMP_IREQREPLY, NULL, 0, "inforeply" }, { ICMP_MASKREQ, NULL, 0, "maskreq" }, { ICMP_MASKREPLY, NULL, 0, "maskreply" }, { -2, NULL, 0, NULL } }; static icmp_subtype_t icmpredirect6[] = { { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, { ICMP6_DST_UNREACH_ADMIN, "admin" }, { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, { ICMP6_DST_UNREACH_ADDR, "address" }, { ICMP6_DST_UNREACH_NOPORT, "noport" }, { -2, NULL } }; static icmp_subtype_t icmptimexceed6[] = { { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, { -2, NULL } }; static icmp_subtype_t icmpparamprob6[] = { { ICMP6_PARAMPROB_HEADER, "header" }, { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, { ICMP6_PARAMPROB_OPTION, "option" }, { -2, NULL } }; static icmp_subtype_t icmpquerysubject6[] = { { ICMP6_NI_SUBJ_IPV6, "ipv6" }, { ICMP6_NI_SUBJ_FQDN, "fqdn" }, { ICMP6_NI_SUBJ_IPV4, "ipv4" }, { -2, NULL }, }; static icmp_subtype_t icmpnodeinfo6[] = { { ICMP6_NI_SUCCESS, "success" }, { ICMP6_NI_REFUSED, "refused" }, { ICMP6_NI_UNKNOWN, "unknown" }, { -2, NULL } }; static icmp_subtype_t icmprenumber6[] = { { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, { -2, NULL } }; static icmp_type_t icmptypes6[] = { { 0, NULL, 0, NULL }, { ICMP6_DST_UNREACH, icmpredirect6, IST_SZ(icmpredirect6), "unreach" }, { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, { ICMP6_TIME_EXCEEDED, icmptimexceed6, IST_SZ(icmptimexceed6), "timxceed" }, { ICMP6_PARAM_PROB, icmpparamprob6, IST_SZ(icmpparamprob6), "paramprob" }, { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, IST_SZ(icmpquerysubject6), "groupmemberquery" }, { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, { ND_REDIRECT, NULL, 0, "redirect" }, { ICMP6_ROUTER_RENUMBERING, icmprenumber6, IST_SZ(icmprenumber6), "routerrenumber" }, { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, { ICMP6_NI_QUERY, icmpnodeinfo6, IST_SZ(icmpnodeinfo6), "nodeinforequest" }, { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, { MLD6_MTRACE, NULL, 0, "mtracerequest" }, { -2, NULL, 0, NULL } }; static icmp_subtype_t * find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz) { icmp_subtype_t *ist; int i; if (tablesz < 2) - return NULL; + return(NULL); if ((type < 0) || (type > table[tablesz - 2].ist_val)) - return NULL; + return(NULL); i = type; if (table[type].ist_val == type) - return table + type; + return(table + type); for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) if (ist->ist_val == type) - return ist; - return NULL; + return(ist); + return(NULL); } static icmp_type_t * find_icmptype(int type, icmp_type_t *table, size_t tablesz) { icmp_type_t *it; int i; if (tablesz < 2) - return NULL; + return(NULL); if ((type < 0) || (type > table[tablesz - 2].it_val)) - return NULL; + return(NULL); i = type; if (table[type].it_val == type) - return table + type; + return(table + type); for (i = 0, it = table; it->it_val != -2; i++, it++) if (it->it_val == type) - return it; - return NULL; + return(it); + return(NULL); } static void handlehup(int sig) { signal(SIGHUP, handlehup); donehup = 1; } static void init_tabs(void) { struct protoent *p; struct servent *s; char *name, **tab; int port, i; if (protocols != NULL) { for (i = 0; i < 256; i++) if (protocols[i] != NULL) { free(protocols[i]); protocols[i] = NULL; } free(protocols); protocols = NULL; } protocols = (char **)malloc(256 * sizeof(*protocols)); if (protocols != NULL) { bzero((char *)protocols, 256 * sizeof(*protocols)); setprotoent(1); while ((p = getprotoent()) != NULL) if (p->p_proto >= 0 && p->p_proto <= 255 && p->p_name != NULL && protocols[p->p_proto] == NULL) protocols[p->p_proto] = strdup(p->p_name); endprotoent(); if (protocols[0]) free(protocols[0]); protocols[0] = strdup("ip"); } if (udp_ports != NULL) { for (i = 0; i < 65536; i++) if (udp_ports[i] != NULL) { free(udp_ports[i]); udp_ports[i] = NULL; } free(udp_ports); udp_ports = NULL; } udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); if (udp_ports != NULL) bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); if (tcp_ports != NULL) { for (i = 0; i < 65536; i++) if (tcp_ports[i] != NULL) { free(tcp_ports[i]); tcp_ports[i] = NULL; } free(tcp_ports); tcp_ports = NULL; } tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); if (tcp_ports != NULL) bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); setservent(1); while ((s = getservent()) != NULL) { if (s->s_proto == NULL) continue; else if (!strcmp(s->s_proto, "tcp")) { port = ntohs(s->s_port); name = s->s_name; tab = tcp_ports; } else if (!strcmp(s->s_proto, "udp")) { port = ntohs(s->s_port); name = s->s_name; tab = udp_ports; } else continue; if ((port < 0 || port > 65535) || (name == NULL)) continue; if (tab != NULL) tab[port] = strdup(name); } endservent(); } static char * getlocalproto(u_int p) { static char pnum[4]; char *s; p &= 0xff; s = protocols ? protocols[p] : NULL; if (s == NULL) { sprintf(pnum, "%u", p); s = pnum; } - return s; + return(s); } static int read_log(int fd, int *lenp, char *buf, int bufsize) { int nr; if (bufsize > IPFILTER_LOGSIZE) bufsize = IPFILTER_LOGSIZE; nr = read(fd, buf, bufsize); if (!nr) - return 2; + return(2); if ((nr < 0) && (errno != EINTR)) - return -1; + return(-1); *lenp = nr; - return 0; + return(0); } char * portlocalname(res, proto, port) int res; char *proto; u_int port; { static char pname[8]; char *s; port = ntohs(port); port &= 0xffff; sprintf(pname, "%u", port); if (!res || (ipmonopts & IPMON_PORTNUM)) - return pname; + return(pname); s = NULL; if (!strcmp(proto, "tcp")) s = tcp_ports[port]; else if (!strcmp(proto, "udp")) s = udp_ports[port]; if (s == NULL) s = pname; - return s; + return(s); } static char * icmpname(u_int type, u_int code) { static char name[80]; icmp_subtype_t *ist; icmp_type_t *it; char *s; s = NULL; it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); if (it != NULL) s = it->it_name; if (s == NULL) sprintf(name, "icmptype(%d)/", type); else sprintf(name, "%s/", s); ist = NULL; if (it != NULL && it->it_subtable != NULL) ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); if (ist != NULL && ist->ist_name != NULL) strcat(name, ist->ist_name); else sprintf(name + strlen(name), "%d", code); - return name; + return(name); } static char * icmpname6(u_int type, u_int code) { static char name[80]; icmp_subtype_t *ist; icmp_type_t *it; char *s; s = NULL; it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); if (it != NULL) s = it->it_name; if (s == NULL) sprintf(name, "icmpv6type(%d)/", type); else sprintf(name, "%s/", s); ist = NULL; if (it != NULL && it->it_subtable != NULL) ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); if (ist != NULL && ist->ist_name != NULL) strcat(name, ist->ist_name); else sprintf(name + strlen(name), "%d", code); - return name; + return(name); } void dumphex(FILE *log, int dopts, char *buf, int len) { char hline[80]; int i, j, k; u_char *s = (u_char *)buf, *t = (u_char *)hline; if (buf == NULL || len == 0) return; *hline = '\0'; for (i = len, j = 0; i; i--, j++, s++) { if (j && !(j & 0xf)) { *t++ = '\n'; *t = '\0'; if ((dopts & IPMON_SYSLOG)) syslog(LOG_INFO, "%s", hline); else if (log != NULL) fputs(hline, log); t = (u_char *)hline; *t = '\0'; } sprintf((char *)t, "%02x", *s & 0xff); t += 2; if (!((j + 1) & 0xf)) { s -= 15; sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); s--; } if ((j + 1) & 0xf) *t++ = ' ';; } if (j & 0xf) { for (k = 16 - (j & 0xf); k; k--) { *t++ = ' '; *t++ = ' '; *t++ = ' '; } sprintf((char *)t, " "); t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); *t++ = '\n'; *t = '\0'; } if ((dopts & IPMON_SYSLOG) != 0) syslog(LOG_INFO, "%s", hline); else if (log != NULL) { fputs(hline, log); fflush(log); } } static struct tm * get_tm(time_t sec) { struct tm *tm; time_t t; t = sec; tm = localtime(&t); - return tm; + return(tm); } static void print_natlog(config_t *conf, char *buf, int blen) { 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 = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; t += i; } (void) strftime(t, len, "%T", tm); t += strlen(t); sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); t += strlen(t); 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); 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); 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); strcpy(t, getlocalproto(nl->nl_p[0])); t += strlen(t); if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { #ifdef USE_QUAD_T # ifdef PRId64 sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" PRId64, # else sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", # endif #else 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]); t += strlen(t); } *t++ = '\n'; *t++ = '\0'; if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); else if (conf->log != NULL) (void) fprintf(conf->log, "%s", line); } static void print_statelog(config_t *conf, char *buf, int blen) { 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 = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; tm = get_tm(ipl->ipl_sec); len = sizeof(line); if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; t += i; } (void) strftime(t, len, "%T", tm); t += strlen(t); sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); family = vtof(sl->isl_v); switch (sl->isl_type) { case ISL_NEW : strcpy(t, "STATE:NEW "); break; case ISL_CLONE : strcpy(t, "STATE:CLONED "); break; case ISL_EXPIRE : if ((sl->isl_p == IPPROTO_TCP) && (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) strcpy(t, "STATE:CLOSE "); else strcpy(t, "STATE:EXPIRE "); break; case ISL_FLUSH : strcpy(t, "STATE:FLUSH "); break; case ISL_INTERMEDIATE : strcpy(t, "STATE:INTERMEDIATE "); break; case ISL_REMOVE : strcpy(t, "STATE:REMOVE "); break; case ISL_KILLED : strcpy(t, "STATE:KILLED "); break; case ISL_UNLOAD : strcpy(t, "STATE:UNLOAD "); break; default : sprintf(t, "Type: %d ", sl->isl_type); break; } t += strlen(t); proto = getlocalproto(sl->isl_p); if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { sprintf(t, "%s,%s -> ", hostname(family, (u_32_t *)&sl->isl_src), portlocalname(res, proto, (u_int)sl->isl_sport)); t += strlen(t); 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) { sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); sprintf(t, "%s PR icmp %d", hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else if (sl->isl_p == IPPROTO_ICMPV6) { sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); sprintf(t, "%s PR icmpv6 %d", hostname(family, (u_32_t *)&sl->isl_dst), sl->isl_itype); } else { sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); t += strlen(t); sprintf(t, "%s PR %s", hostname(family, (u_32_t *)&sl->isl_dst), proto); } t += strlen(t); if (sl->isl_tag != FR_NOLOGTAG) { sprintf(t, " tag %u", sl->isl_tag); t += strlen(t); } if (sl->isl_type != ISL_NEW) { sprintf(t, #ifdef USE_QUAD_T #ifdef PRId64 " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 " Pkts out %" PRId64 " Bytes out %" PRId64 " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 " Pkts out %" PRId64 " Bytes out %" PRId64, #else " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd", #endif /* PRId64 */ #else " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld", #endif sl->isl_pkts[0], sl->isl_bytes[0], sl->isl_pkts[1], sl->isl_bytes[1], sl->isl_pkts[2], sl->isl_bytes[2], sl->isl_pkts[3], sl->isl_bytes[3]); t += strlen(t); } *t++ = '\n'; *t++ = '\0'; if (ipmonopts & IPMON_SYSLOG) syslog(LOG_INFO, "%s", line); else if (conf->log != NULL) (void) fprintf(conf->log, "%s", line); } static void print_log(config_t *conf, logsource_t *log, char *buf, int blen) { char *bp, *bpo; iplog_t *ipl; int psize; bp = NULL; bpo = NULL; while (blen > 0) { ipl = (iplog_t *)buf; if ((u_long)ipl & (sizeof(long)-1)) { if (bp) bpo = bp; bp = (char *)malloc(blen); bcopy((char *)ipl, bp, blen); if (bpo) { free(bpo); bpo = NULL; } buf = bp; continue; } psize = ipl->ipl_dsize; if (psize > blen) break; if (conf->blog != NULL) { fwrite(buf, psize, 1, conf->blog); fflush(conf->blog); } if (log->logtype == IPL_LOGIPF) { if (ipl->ipl_magic == IPL_MAGIC) print_ipflog(conf, buf, psize); } else if (log->logtype == IPL_LOGNAT) { if (ipl->ipl_magic == IPL_MAGIC_NAT) print_natlog(conf, buf, psize); } else if (log->logtype == IPL_LOGSTATE) { if (ipl->ipl_magic == IPL_MAGIC_STATE) print_statelog(conf, buf, psize); } blen -= psize; buf += psize; } if (bp) free(bp); return; } static void print_ipflog(config_t *conf, char *buf, int blen) { 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; tcphdr_t *tp; #ifdef USE_INET6 struct ip6_ext *ehp; u_short ehl; ip6_t *ip6; int go; #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)); f = ipf->fl_family; res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; t = line; *t = '\0'; tm = get_tm(ipl->ipl_sec); len = sizeof(line); if (!(ipmonopts & IPMON_SYSLOG)) { (void) strftime(t, len, "%d/%m/%Y ", tm); i = strlen(t); len -= i; t += i; } (void) strftime(t, len, "%T", tm); t += strlen(t); sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); t += strlen(t); if (ipl->ipl_count > 1) { sprintf(t, "%dx ", ipl->ipl_count); t += strlen(t); } { char ifname[sizeof(ipf->fl_ifname) + 1]; strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); ifname[sizeof(ipf->fl_ifname)] = '\0'; sprintf(t, "%s", ifname); t += strlen(t); # if SOLARIS if (ISALPHA(*(t - 1))) { sprintf(t, "%d", ipf->fl_unit); t += strlen(t); } # endif } if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) strcat(t, " @-1:"); else if (ipf->fl_group[0] == '\0') (void) strcpy(t, " @0:"); else sprintf(t, " @%s:", ipf->fl_group); t += strlen(t); if (ipf->fl_rule == 0xffffffff) strcat(t, "-1 "); else sprintf(t, "%u ", ipf->fl_rule + 1); t += strlen(t); lvl = LOG_NOTICE; if (ipf->fl_lflags & FI_SHORT) { *t++ = 'S'; lvl = LOG_ERR; } if (FR_ISPASS(ipf->fl_flags)) { if (ipf->fl_flags & FR_LOGP) *t++ = 'p'; else *t++ = 'P'; } else if (FR_ISBLOCK(ipf->fl_flags)) { if (ipf->fl_flags & FR_LOGB) *t++ = 'b'; else *t++ = 'B'; lvl = LOG_WARNING; } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { *t++ = 'L'; lvl = LOG_INFO; } else if (ipf->fl_flags & FF_LOGNOMATCH) { *t++ = 'n'; } else { *t++ = '?'; lvl = LOG_EMERG; } if (ipf->fl_loglevel != 0xffff) lvl = ipf->fl_loglevel; *t++ = ' '; *t = '\0'; 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); ip6 = (ip6_t *)ip; p = (u_short)ip6->ip6_nxt; s = (u_32_t *)&ip6->ip6_src; d = (u_32_t *)&ip6->ip6_dst; plen = hl + ntohs(ip6->ip6_plen); go = 1; ehp = (struct ip6_ext *)((char *)ip6 + hl); while (go == 1) { switch (p) { case IPPROTO_HOPOPTS : case IPPROTO_MOBILITY : case IPPROTO_DSTOPTS : case IPPROTO_ROUTING : case IPPROTO_AH : p = ehp->ip6e_nxt; ehl = 8 + (ehp->ip6e_len << 3); hl += ehl; ehp = (struct ip6_ext *)((char *)ehp + ehl); break; case IPPROTO_FRAGMENT : hl += sizeof(struct ip6_frag); /* FALLTHROUGH */ default : go = 0; break; } } } else #endif { goto printipflog; } proto = getlocalproto(p); if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { tp = (tcphdr_t *)((char *)ip + hl); if (!(ipf->fl_lflags & FI_SHORT)) { sprintf(t, "%s,%s -> ", hostname(f, s), portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); 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); if (p == IPPROTO_TCP) { *t++ = ' '; *t++ = '-'; for (i = 0; tcpfl[i].value; i++) if (tp->th_flags & tcpfl[i].value) *t++ = tcpfl[i].flag; 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)); t += strlen(t); } } *t = '\0'; } else { sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); sprintf(t, "%s PR %s len %hu %hu", hostname(f, d), proto, hl, plen); } #if defined(AF_INET6) && defined(IPPROTO_ICMPV6) } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { ic = (struct icmp *)((char *)ip + hl); sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", hostname(f, d), hl, plen, icmpname6(ic->icmp_type, ic->icmp_code)); #endif } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { ic = (struct icmp *)((char *)ip + hl); sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); 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 || ic->icmp_type == ICMP_PARAMPROB || ic->icmp_type == ICMP_REDIRECT || ic->icmp_type == ICMP_TIMXCEED) { ipc = &ic->icmp_ip; i = ntohs(ipc->ip_len); /* * XXX - try to guess endian of ip_len in ICMP * returned data. */ if (i > 1500) i = ipc->ip_len; ipoff = ntohs(ipc->ip_off); 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); sprintf(t, " for %s,%s -", HOSTNAMEV4(ipc->ip_src), portlocalname(res, proto, (u_int)tp->th_sport)); t += strlen(t); 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) && (ipc->ip_p == IPPROTO_ICMP)) { icmp = (icmphdr_t *)((char *)ipc + hl); t += strlen(t); sprintf(t, " for %s -", HOSTNAMEV4(ipc->ip_src)); t += strlen(t); sprintf(t, " %s PR icmp len %hu %hu icmp %d/%d", HOSTNAMEV4(ipc->ip_dst), IP_HL(ipc) << 2, i, icmp->icmp_type, icmp->icmp_code); } else { t += strlen(t); sprintf(t, " for %s -", HOSTNAMEV4(ipc->ip_src)); t += strlen(t); 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) { sprintf(t, "(frag %d:%hu@%hu%s%s)", ntohs(ipc->ip_id), i - (IP_HL(ipc) << 2), (ipoff & IP_OFFMASK) << 3, ipoff & IP_MF ? "+" : "", ipoff & IP_DF ? "-" : ""); } } } } else { sprintf(t, "%s -> ", hostname(f, s)); t += strlen(t); sprintf(t, "%s PR %s len %hu (%hu)", hostname(f, d), proto, hl, plen); t += strlen(t); if (off & IP_OFFMASK) sprintf(t, " (frag %d:%hu@%hu%s%s)", ntohs(ip->ip_id), plen - hl, (off & IP_OFFMASK) << 3, ipoff & IP_MF ? "+" : "", ipoff & IP_DF ? "-" : ""); } t += strlen(t); printipflog: if (ipf->fl_flags & FR_KEEPSTATE) { (void) strcpy(t, " K-S"); t += strlen(t); } if (ipf->fl_flags & FR_KEEPFRAG) { (void) strcpy(t, " K-F"); t += strlen(t); } if (ipf->fl_dir == 0) strcpy(t, " IN"); else if (ipf->fl_dir == 1) strcpy(t, " OUT"); t += strlen(t); if (ipf->fl_logtag != 0) { sprintf(t, " log-tag %d", ipf->fl_logtag); t += strlen(t); } if (ipf->fl_nattag.ipt_num[0] != 0) { strcpy(t, " nat-tag "); t += strlen(t); strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); t += strlen(t); } if ((ipf->fl_lflags & FI_LOWTTL) != 0) { strcpy(t, " low-ttl"); t += 8; } if ((ipf->fl_lflags & FI_OOW) != 0) { strcpy(t, " OOW"); t += 4; } if ((ipf->fl_lflags & FI_BAD) != 0) { strcpy(t, " bad"); t += 4; } if ((ipf->fl_lflags & FI_NATED) != 0) { strcpy(t, " NAT"); t += 4; } if ((ipf->fl_lflags & FI_BADNAT) != 0) { strcpy(t, " bad-NAT"); t += 8; } if ((ipf->fl_lflags & FI_BADSRC) != 0) { strcpy(t, " bad-src"); t += 8; } if ((ipf->fl_lflags & FI_MULTICAST) != 0) { strcpy(t, " multicast"); t += 10; } if ((ipf->fl_lflags & FI_BROADCAST) != 0) { strcpy(t, " broadcast"); t += 10; } if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == FI_MBCAST) { 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->cfile != NULL) defaction = check_action(buf, line, ipmonopts, lvl); if (defaction == 0) { if (ipmonopts & IPMON_SYSLOG) { syslog(lvl, "%s", line); } else if (conf->log != NULL) { (void) fprintf(conf->log, "%s", line); } if (ipmonopts & IPMON_HEXHDR) { dumphex(conf->log, ipmonopts, buf, sizeof(iplog_t) + sizeof(*ipf)); } if (ipmonopts & IPMON_HEXBODY) { dumphex(conf->log, ipmonopts, (char *)ip, ipf->fl_plen + 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(char *prog) { fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B ] [ -C ]\n" "\t[ -f ] [ -L ] [ -N ]\n" "\t[ -o [NSI] ] [ -O [NSI] ] [ -P ] [ -S ]\n" "\t[ ]\n", prog); exit(1); } static void write_pid(char *file) { FILE *fp = NULL; int fd; if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { fp = fdopen(fd, "w"); if (fp == NULL) { close(fd); fprintf(stderr, "unable to open/create pid file: %s\n", file); return; } fprintf(fp, "%d", getpid()); fclose(fp); } } static void flushlogs(char *file, FILE *log) { int fd, flushed = 0; if ((fd = open(file, O_RDWR)) == -1) { (void) fprintf(stderr, "%s: open: %s\n", file, STRERROR(errno)); exit(1); } if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { printf("%d bytes flushed from log buffer\n", flushed); fflush(stdout); } else ipferror(fd, "SIOCIPFFB"); (void) close(fd); if (flushed) { if (ipmonopts & IPMON_SYSLOG) { syslog(LOG_INFO, "%d bytes flushed from log\n", flushed); } else if ((log != stdout) && (log != NULL)) { fprintf(log, "%d bytes flushed from log\n", flushed); } } } static void logopts(int turnon, char *options) { int flags = 0; char *s; for (s = options; *s; s++) { switch (*s) { case 'N' : flags |= IPMON_NAT; break; case 'S' : flags |= IPMON_STATE; break; case 'I' : flags |= IPMON_FILTER; break; default : fprintf(stderr, "Unknown log option %c\n", *s); exit(1); } } if (turnon) ipmonopts |= flags; else 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(int argc, char *argv[]) { int doread, c, make_daemon = 0; char *prog; config_t config; prog = strrchr(argv[0], '/'); if (prog == NULL) prog = argv[0]; else prog++; initconfig(&config); while ((c = getopt(argc, argv, "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) switch (c) { case 'a' : ipmonopts |= IPMON_LOGALL; config.logsrc[0].logtype = IPL_LOGIPF; config.logsrc[1].logtype = IPL_LOGNAT; config.logsrc[2].logtype = IPL_LOGSTATE; break; case 'b' : ipmonopts |= IPMON_LOGBODY; break; case 'B' : config.bfile = optarg; config.blog = fopen(optarg, "a"); break; case 'C' : config.cfile = optarg; break; case 'D' : make_daemon = 1; break; case 'f' : case 'I' : ipmonopts |= IPMON_FILTER; config.logsrc[0].logtype = IPL_LOGIPF; config.logsrc[0].file = optarg; break; case 'F' : 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); if (logfac == -1) { fprintf(stderr, "Unknown syslog facility '%s'\n", optarg); exit(1); } break; case 'n' : ipmonopts |= IPMON_RESOLVE; opts &= ~OPT_NORESOLVE; break; case 'N' : ipmonopts |= IPMON_NAT; config.logsrc[1].logtype = IPL_LOGNAT; config.logsrc[1].file = optarg; break; case 'o' : case 'O' : logopts(c == 'o', optarg); 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' : ipmonopts |= IPMON_PORTNUM; break; case 'P' : pidfile = optarg; break; case 's' : ipmonopts |= IPMON_SYSLOG; config.log = NULL; break; case 'S' : ipmonopts |= IPMON_STATE; config.logsrc[2].logtype = IPL_LOGSTATE; config.logsrc[2].file = optarg; break; case 't' : ipmonopts |= IPMON_TAIL; break; case 'v' : ipmonopts |= IPMON_VERBOSE; break; case 'x' : ipmonopts |= IPMON_HEXBODY; break; case 'X' : ipmonopts |= IPMON_HEXHDR; break; default : case 'h' : case '?' : usage(argv[0]); } if (ipmonopts & IPMON_SYSLOG) openlog(prog, LOG_NDELAY|LOG_PID, logfac); init_tabs(); if (config.cfile) if (load_config(config.cfile) == -1) { unload_config(); exit(1); } /* * Default action is to only open the filter log file. */ if ((config.logsrc[0].logtype == -1) && (config.logsrc[0].logtype == -1) && (config.logsrc[0].logtype == -1)) config.logsrc[0].logtype = IPL_LOGIPF; openlogs(&config); 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(config.log, NULL, _IONBF, 0); } else { config.log = NULL; } if (make_daemon && ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { #ifdef BSD daemon(0, !(ipmonopts & IPMON_SYSLOG)); #else int pid; 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 ((ipmonopts & IPMON_SYSLOG)) close(2); #endif /* !BSD */ close(0); close(1); write_pid(pidfile); } signal(SIGHUP, handlehup); for (doread = 1; doread; ) doread = read_loginfo(&config); 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 (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; + return(1); if (n == -1) { if (errno == EINTR) - return 1; - return -1; + 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; + 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; } conf->log = fopen(conf->file, "a"); } if (conf->bfile != NULL) { if (conf->blog != NULL) { fclose(conf->blog); conf->blog = NULL; } 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; + 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; + 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 && (ipmonopts & IPMON_TAIL)) sleep(1); - return 1; + return(1); } diff --git a/sbin/ipf/ipmon/ipmon_y.y b/sbin/ipf/ipmon/ipmon_y.y index d94bb1151af8..c70e17adcec0 100644 --- a/sbin/ipf/ipmon/ipmon_y.y +++ b/sbin/ipf/ipmon/ipmon_y.y @@ -1,1038 +1,1038 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include "ipf.h" #include #undef OPT_NAT #undef OPT_VERBOSE #include "ipmon_l.h" #include "ipmon.h" #include #define YYDEBUG 1 extern void yyerror(char *); extern int yyparse(void); extern int yylex(void); extern int yydebug; extern FILE *yyin; extern int yylineNum; extern int ipmonopts; 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(opt_t *, ipmon_doing_t *); static opt_t *new_opt(int); static void free_action(ipmon_action_t *); static void print_action(ipmon_action_t *); static int find_doing(char *); static ipmon_doing_t *build_doing(char *, char *); static void print_match(ipmon_action_t *); static int install_saver(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_s *opt; union i6addr ip6; struct ipmon_doing_s *ipmd; } %token YY_NUMBER YY_HEX %token YY_STR %token 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 IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT %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_DOING IPM_TYPE IPM_NAT %token IPM_STATE IPM_NATTAG IPM_IPF %type ipv4 %type direction dstip dstport every group interface %type protocol result rule srcip srcport logtag matching %type matchopt nattag type %type typeopt %type doopt doing %% file: action | file action ; action: line ';' | assign ';' | IPM_COMMENT | YY_COMMENT ; 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: '=' { yyvarnext = 1; } ; matching: matchopt { $$ = $1; } | matchopt ',' matching { $1->o_next = $3; $$ = $1; } ; matchopt: direction { $$ = $1; } | dstip { $$ = $1; } | dstport { $$ = $1; } | every { $$ = $1; } | group { $$ = $1; } | interface { $$ = $1; } | protocol { $$ = $1; } | result { $$ = $1; } | rule { $$ = $1; } | srcip { $$ = $1; } | srcport { $$ = $1; } | logtag { $$ = $1; } | nattag { $$ = $1; } | type { $$ = $1; } ; doing: doopt { $$ = $1; } | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } ; doopt: 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: IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION); $$->o_num = IPM_IN; } | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION); $$->o_num = IPM_OUT; } ; dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP); $$->o_ip = $3; $$->o_num = $5; } ; dstport: IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT); $$->o_num = $3; } | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT); $$->o_str = $3; } ; every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND); $$->o_num = 1; } | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND); $$->o_num = $2; } | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET); $$->o_num = 1; } | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET); $$->o_num = $2; } ; group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP); $$->o_num = $3; } | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP); $$->o_str = $3; } ; interface: IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE); $$->o_str = $3; } ; logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG); $$->o_num = $3; } ; nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG); $$->o_str = $3; } ; protocol: IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL); $$->o_num = $3; } | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL); $$->o_num = getproto($3); free($3); } ; result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT); $$->o_str = $3; } ; rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE); $$->o_num = YY_NUMBER; } ; srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP); $$->o_ip = $3; $$->o_num = $5; } ; srcport: IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT); $$->o_num = $3; } | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT); $$->o_str = $3; } ; type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE); $$->o_num = $3; } ; typeopt: IPM_IPF { $$ = IPL_MAGIC; } | IPM_NAT { $$ = IPL_MAGIC_NAT; } | IPM_STATE { $$ = IPL_MAGIC_STATE; } ; 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; + return(0); } $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; $$.s_addr = htonl($$.s_addr); } %% static struct wordtab yywords[] = { { "body", IPM_BODY }, { "direction", IPM_DIRECTION }, { "do", IPM_DO }, { "dstip", IPM_DSTIP }, { "dstport", IPM_DSTPORT }, { "every", IPM_EVERY }, { "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 }, { "out", IPM_OUT }, { "packet", IPM_PACKET }, { "packets", IPM_PACKETS }, { "protocol", IPM_PROTOCOL }, { "result", IPM_RESULT }, { "rule", IPM_RULE }, { "second", IPM_SECOND }, { "seconds", IPM_SECONDS }, { "srcip", IPM_SRCIP }, { "srcport", IPM_SRCPORT }, { "state", IPM_STATE }, { "with", IPM_WITH }, { NULL, 0 } }; static int macflags[17][2] = { { IPM_DIRECTION, IPMAC_DIRECTION }, { IPM_DSTIP, IPMAC_DSTIP }, { IPM_DSTPORT, IPMAC_DSTPORT }, { IPM_GROUP, IPMAC_GROUP }, { IPM_INTERFACE, IPMAC_INTERFACE }, { IPM_LOGTAG, IPMAC_LOGTAG }, { IPM_NATTAG, IPMAC_NATTAG }, { IPM_PACKET, IPMAC_EVERY }, { IPM_PROTOCOL, IPMAC_PROTOCOL }, { IPM_RESULT, IPMAC_RESULT }, { IPM_RULE, IPMAC_RULE }, { IPM_SECOND, IPMAC_EVERY }, { IPM_SRCIP, IPMAC_SRCIP }, { IPM_SRCPORT, IPMAC_SRCPORT }, { IPM_TYPE, IPMAC_TYPE }, { IPM_WITH, IPMAC_WITH }, { 0, 0 } }; static opt_t * new_opt(int type) { opt_t *o; o = (opt_t *)calloc(1, sizeof(*o)); o->o_type = type; o->o_line = yylineNum; o->o_logfac = -1; o->o_logpri = -1; - return o; + return(o); } static void build_action(opt_t *olist, ipmon_doing_t *todo) { ipmon_action_t *a; opt_t *o; 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 * once per matching statement. */ for (i = 0; macflags[i][0]; i++) if (macflags[i][0] == o->o_type) break; if (macflags[i][1] & a->ac_mflag) { fprintf(stderr, "%s redfined on line %d\n", yykeytostr(o->o_type), yylineNum); if (o->o_str != NULL) free(o->o_str); olist = o->o_next; free(o); continue; } a->ac_mflag |= macflags[i][1]; switch (o->o_type) { case IPM_DIRECTION : a->ac_direction = o->o_num; break; case IPM_DSTIP : a->ac_dip = o->o_ip.s_addr; a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num)); break; case IPM_DSTPORT : a->ac_dport = htons(o->o_num); break; case IPM_INTERFACE : a->ac_iface = o->o_str; o->o_str = NULL; break; case IPM_GROUP : if (o->o_str != NULL) strncpy(a->ac_group, o->o_str, FR_GROUPLEN); else sprintf(a->ac_group, "%d", o->o_num); break; case IPM_LOGTAG : a->ac_logtag = o->o_num; break; case IPM_NATTAG : strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag)); break; case IPM_PACKET : a->ac_packet = o->o_num; break; case IPM_PROTOCOL : a->ac_proto = o->o_num; break; case IPM_RULE : a->ac_rule = o->o_num; break; case IPM_RESULT : if (!strcasecmp(o->o_str, "pass")) a->ac_result = IPMR_PASS; else if (!strcasecmp(o->o_str, "block")) a->ac_result = IPMR_BLOCK; else if (!strcasecmp(o->o_str, "nomatch")) a->ac_result = IPMR_NOMATCH; else if (!strcasecmp(o->o_str, "log")) a->ac_result = IPMR_LOG; break; case IPM_SECOND : a->ac_second = o->o_num; break; case IPM_SRCIP : a->ac_sip = o->o_ip.s_addr; a->ac_smsk = htonl(0xffffffff << (32 - o->o_num)); break; case IPM_SRCPORT : a->ac_sport = htons(o->o_num); break; case IPM_TYPE : a->ac_type = o->o_num; break; case IPM_WITH : break; default : break; } olist = o->o_next; if (o->o_str != NULL) 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(char *buf, char *log, int opts, int 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; int matched; u_long t1; ip_t *ip; matched = 0; ipl = (iplog_t *)buf; ipf = (ipflog_t *)(ipl +1); 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) { verbose(8, "-- direction not in\n"); continue; } } else if (a->ac_direction == IPM_OUT) { 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)) { verbose(8, "-- type mismatch\n"); continue; } if ((a->ac_mflag & IPMAC_EVERY) != 0) { gettimeofday(&tv, NULL); t1 = tv.tv_sec - a->ac_lastsec; if (tv.tv_usec <= a->ac_lastusec) t1--; if (a->ac_second != 0) { if (t1 < a->ac_second) { verbose(8, "-- too soon\n"); continue; } a->ac_lastsec = tv.tv_sec; a->ac_lastusec = tv.tv_usec; } if (a->ac_packet != 0) { if (a->ac_pktcnt == 0) 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) { verbose(8, "-- dstip wrong\n"); continue; } } if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 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) { verbose(8, "-- dport mismatch\n"); continue; } } if ((a->ac_mflag & IPMAC_GROUP) != 0) { if (strncmp(a->ac_group, ipf->fl_group, FR_GROUPLEN) != 0) { verbose(8, "-- group mismatch\n"); continue; } } if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 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) { 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) { verbose(8, "-- ff-flags mismatch\n"); continue; } } else if (FR_ISPASS(ipf->fl_flags)) { 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) { verbose(8, "-- block mismatch\n"); continue; } } else { /* Log only */ 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) { 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) { verbose(8, "-- srcip mismatch\n"); continue; } } if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 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) { verbose(8, "-- sport mismatch\n"); continue; } } if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 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) { verbose(8, "-- nattag mismatch\n"); continue; } } matched = 1; verbose(8, "++ matched\n"); /* * It matched so now perform the saves */ for (d = a->ac_doing; d != NULL; d = d->ipmd_next) (*d->ipmd_store)(d->ipmd_token, &msg); } - return matched; + return(matched); } static void free_action(ipmon_action_t *a) { 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; } a->ac_next = NULL; free(a); } int load_config(char *file) { FILE *fp; char *s; unload_config(); s = getenv("YYDEBUG"); if (s != NULL) yydebug = atoi(s); else yydebug = 0; yylineNum = 1; (void) yysettab(yywords); fp = fopen(file, "r"); if (!fp) { perror("load_config:fopen:"); - return -1; + return(-1); } yyin = fp; while (!feof(fp)) yyparse(); fclose(fp); - return 0; + return(0); } void unload_config(void) { 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(void) { ipmon_action_t *a; for (a = alist; a != NULL; a = a->ac_next) { print_action(a); printf("#\n"); } } static void print_action(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(ipmon_saver_t *saver) { ipmon_saver_int_t *it; if (find_doing(saver->ims_name) == IPM_DOING) - return NULL; + return(NULL); it = calloc(1, sizeof(*it)); if (it == NULL) - return NULL; + return(NULL); it->imsi_stor = saver; it->imsi_next = saverlist; saverlist = it; - return it; + return(it); } static int find_doing(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(IPM_DOING); } - return 0; + return(0); } static ipmon_doing_t * build_doing(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; + 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; + 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; + 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; + return(d); } static void print_match(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(char *name, char *path) { ipmon_saver_int_t *isi; ipmon_saver_t *is; char nbuf[80]; if (find_doing(name) == IPM_DOING) - return -1; + return(-1); isi = calloc(1, sizeof(*isi)); if (isi == NULL) - return -1; + 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; + return(0); loaderror: if (isi->imsi_handle != NULL) dlclose(isi->imsi_handle); free(isi); if (is != NULL) free(is); - return -1; + return(-1); } diff --git a/sbin/ipf/ipnat/ipnat.5 b/sbin/ipf/ipnat/ipnat.5 index ab56573d79ea..00d186ad9f40 100644 --- a/sbin/ipf/ipnat/ipnat.5 +++ b/sbin/ipf/ipnat/ipnat.5 @@ -1,728 +1,728 @@ .\" $FreeBSD$ .\" .TH IPNAT 5 .SH NAME ipnat, ipnat.conf \- IPFilter NAT file format .SH DESCRIPTION .PP The .B ipnat.conf file is used to specify rules for the Network Address Translation (NAT) component of IPFilter. To load rules specified in the .B ipnat.conf file, the .B ipnat(8) program is used. .PP For standard NAT functionality, a rule should start with \fBmap\fP and then proceeds to specify the interface for which outgoing packets will have their source address rewritten. Following this it is expected that the old source address, and optionally port number, will be specified. .PP In general, all NAT rules conform to the following layout: the first word indicates what type of NAT rule is present, this is followed by some stanzas to match a packet, followed by a "->" and this is then followed by several more stanzas describing the new data to be put in the packet. .PP In this text and in others, use of the term "left hand side" (LHS) when talking about a NAT rule refers to text that appears before the "->" and the "right hand side" (RHS) for text that appears after it. In essence, the LHS is the packet matching and the RHS is the new data to be used. .SH VARIABLES .PP This configuration file, like all others used with IPFilter, supports the use of variable substitution throughout the text. .nf nif="ppp0"; map $nif 0/0 -> 0/32 .fi .PP would become .nf map ppp0 0/0 -> 0/32 .fi .PP Variables can be used recursively, such as 'foo="$bar baz";', so long as $bar exists when the parser reaches the assignment for foo. .PP See .B ipnat(8) for instructions on how to define variables to be used from a shell environment. .SH OUTBOUND SOURCE TRANSLATION (map'ing) Changing the source address of a packet is traditionally performed using .B map rules. Both the source address and optionally port number can be changed according to various controls. .PP To start out with, a common rule used is of the form: .nf map le0 0/0 -> 0/32 .fi .PP Here we're saying change the source address of all packets going out of le0 (the address/mask pair of 0/0 matching all packets) to that of the interface le0 (0/32 is a synonym for the interface's own address at the current point in time.) If we wanted to pass the packet through with no change in address, we would write it as: .nf map le0 0/0 -> 0/0 .fi .PP If we only want to change a portion of our internal network and to a different address that is routed back through this host, we might do: .nf map le0 10.1.1.0/24 -> 192.168.55.3/32 .fi .PP In some instances, we may have an entire subnet to map internal addresses out onto, in which case we can express the translation as this: .nf map le0 10.0.0.0/8 -> 192.168.55.0/24 .fi .PP IPFilter will cycle through each of the 256 addresses in the 192.168.55.0/24 address space to ensure that they all get used. .PP Of course this poses a problem for TCP and UDP, with many connections made, each with its own port number pair. If we're unlucky, translations can be dropped because the new address/port pair mapping already exists. To mitigate this problem, we add in port translation or port mapping: .nf map le0 10.0.0.0/8 -> 192.168.55.0/24 portmap tcp/udp auto .fi .PP In this instance, the word "auto" tells IPFilter to calculate a private range of port numbers for each address on the LHS to use without fear of them being trampled by others. This can lead to problems if there are connections being generated more quickly than IPFilter can expire them. In this instance, and if we want to get away from a private range of port numbers, we can say: .nf map le0 10.0.0.0/8 -> 192.168.55.0/24 portmap tcp/udp 5000:65000 .fi .PP And now each connection through le0 will add to the enumeration of the port number space 5000-65000 as well as the IP address subnet of 192.168.55.0/24. .PP If the new addresses to be used are in a consecutive range, rather than a complete subnet, we can express this as: .nf map le0 10.0.0.0/8 -> range 192.168.55.10-192.168.55.249 portmap tcp/udp 5000:65000 .fi .PP This tells IPFilter that it has a range of 240 IP address to use, from 192.168.55.10 to 192.168.55.249, inclusive. .PP If there were several ranges of addresses for use, we can use each one in a round-robin fashion as followed: .nf map le0 10.0.0.0/8 -> range 192.168.55.10-192.168.55.29 portmap tcp/udp 5000:65000 round-robin map le0 10.0.0.0/8 -> range 192.168.55.40-192.168.55.49 portmap tcp/udp 5000:65000 round-robin .fi .PP To specify translation rules that impact a specific IP protocol, the protocol name or number is appended to the rule like this: .nf map le0 10.0.0.0/8 -> 192.168.55.0/24 tcp/udp map le0 10.0.0.0/8 -> 192.168.55.1/32 icmp map le0 10.0.0.0/8 -> 192.168.55.2/32 gre .fi .PP For TCP connections exiting a connection such as PPPoE where the MTU is slightly smaller than normal ethernet, it can be useful to reduce the Maximum Segment Size (MSS) offered by the internal machines to match, reducing the liklihood that the either end will attempt to send packets that are too big and result in fragmentation. This is acheived using the .B mssclamp option with TCP .B map rules like this: .nf map pppoe0 0/0 -> 0/32 mssclamp 1400 tcp .fi .PP For ICMP packets, we can map the ICMP id space in query packets: .nf map le0 10.0.0.0/8 -> 192.168.55.1/32 icmpidmap icmp 1000:20000 .fi .PP If we wish to be more specific about our initial matching criteria on the LHS, we can expand to using a syntax more similar to that in .B ipf.conf(5) : .nf map le0 from 10.0.0.0/8 to 26.0.0.0/8 -> 192.168.55.1 map le0 from 10.0.0.0/8 port > 1024 to 26.0.0.0/8 -> 192.168.55.2 portmap 5000:9999 tcp/udp map le0 from 10.0.0.0/8 ! to 26.0.0.0/8 -> 192.168.55.3 portmap 5000:9999 tcp/udp .fi .TP .B NOTE: negation matching with source addresses is .B NOT possible with .B map / .B map-block rules. .PP The NAT code has builtin default timeouts for TCP, UDP, ICMP and another for all other protocols. In general, the timeout for an entry to be deleted shrinks once a reply packet has been seen (excluding TCP.) If you wish to specify your own timeouts, this can be achieved either by setting one timeout for both directions: .nf map le0 0/0 -> 0/32 gre age 30 .fi .PP or setting a different timeout for the reply: .nf map le0 from any to any port = 53 -> 0/32 age 60/10 udp .fi .PP A pressing problem that many people encounter when using NAT is that the address protocol can be embedded inside an application's communication. To address this problem, IPFilter provides a number of built-in proxies for the more common trouble makers, such as FTP. These proxies can be used as follows: .nf map le0 0/0 -> 0/32 proxy port 21 ftp/tcp .fi .PP In this rule, the word "proxy" tells us that we want to connect up this translation with an internal proxy. The "port 21" is an extra restriction that requires the destination port number to be 21 if this rule is to be activated. The word "ftp" is the proxy identifier that the kernel will try and resolve internally, "tcp" the protocol that packets must match. .PP See below for a list of proxies and their relative staus. .PP To associate NAT rules with filtering rules, it is possible to set and match tags during either inbound or outbound processing. At present the tags for forwarded packets are not preserved by forwarding, so once the packet leaves IPFilter, the tag is forgotten. For .B map rules, we can match tags set by filter rules like this: .nf map le0 0/0 -> 0/32 proxy portmap 5000:5999 tag lan1 tcp .fi .PP This would be used with "pass out" rules that includes a stanza such as "set-tag (nat = lan1)". .PP If the interface in which packets are received is different from the interface on which packets are sent out, then the translation rule needs to be written to take this into account: .nf map hme0,le0 0/0 -> 0/32 .fi .PP Although this might seem counterintuitive, the interfaces when listed in rules for .B ipnat.conf are always in the .I inbound , .I outbound -order. In this case, hme0 would be the return interface and le0 would be -the outgoing interface. If you wish to allow return packets on any +order.( In this case, hme0 would be the return interface and le0 would be); +the( outgoing interface. If you wish to allow return packets on any); interface, the correct syntax to use would be: .nf map *,le0 0/0 -> 0/32 .fi .LP A special variant of .B map rules exists, called .B map-block. This command is intended for use when there is a large network to be mapped onto a smaller network, where the difference in netmasks is upto 14 bits difference in size. This is achieved by dividing the address space and port space up to ensure that each source address has its own private range of ports to use. For example, this rule: .nf map-block ppp0 172.192.0.0/16 -> 209.1.2.0/24 ports auto .fi .PP would result in 172.192.0.0/24 being mapped to 209.1.2.0/32 with each address, from 172.192.0.0 to 172.192.0.255 having 252 ports of its own. As opposed to the above use of \fBmap\fP, if for some reason the user of (say) 172.192.0.2 wanted 260 simultaneous connections going out, they would be limited to 252 with \fBmap-block\fP but would just \fImove on\fP to the next IP address with the \fBmap\fP command. .SS Extended matching .PP If it is desirable to match on both the source and destination of a packet before applying an address translation to it, this can be achieved by using the same from-to syntax as is used in \fBipf.conf\fP(5). What follows applies equally to the .B map rules discussed above and .B rdr rules discussed below. A simple example is as follows: .nf map bge0 from 10.1.0.0/16 to 192.168.1.0/24 -> 172.12.1.4 .fi .PP This would only match packets that are coming from hosts that have a source address matching 10.1.0.0/16 and a destination matching 192.168.1.0/24. This can be expanded upon with ports for TCP like this: .nf rdr bge0 from 10.1.0.0/16 to any port = 25 -> 127.0.0.1 port 2501 tcp .fi .PP Where only TCP packets from 10.1.0.0/16 to port 25 will be redirected to port 2501. .PP As with \fBipf.conf\fR(5), if we have a large set of networks or addresses that we would like to match up with then we can define a pool using \fBippool\fR(8) in \fBippool.conf\fR(5) and then refer to it in an \fBipnat\fR rule like this: .nf map bge0 from pool/100 to any port = 25 -> 127.0.0.1 port 2501 tcp .fi .TP .B NOTE: In this situation, the rule is considered to have a netmask of "0" and thus is looked at last, after any rules with /16's or /24's in them, .I even if the defined pool only has /24's or /32's. Pools may also be used .I wherever the from-to syntax in \fBipnat.conf\fR(5) is allowed. .SH INBOUND DESTINATION TRANSLATION (redirection) .PP Redirection of packets is used to change the destination fields in a packet and is supported for packets that are moving \fIin\fP on a network interface. While the same general syntax for .B map rules is supported, there are differences and limitations. .PP Firstly, by default all redirection rules target a single IP address, not a network or range of network addresses, so a rule written like this: .nf rdr le0 0/0 -> 192.168.1.0 .fi .PP Will not spread packets across all 256 IP addresses in that class C network. If you were to try a rule like this: .nf rdr le0 0/0 -> 192.168.1.0/24 .fi .PP then you will receive a parsing error. .PP The from-to source-destination matching used with .B map rules can be used with rdr rules, along with negation, however the restriction moves - only a source address match can be negated: .nf rdr le0 from 1.1.0.0/16 to any -> 192.168.1.3 rdr le0 ! from 1.1.0.0/16 to any -> 192.168.1.4 .fi .PP If there is a consective set of addresses you wish to spread the packets over, then this can be done in one of two ways, the word "range" optional to preserve: .nf rdr le0 0/0 -> 192.168.1.1 - 192.168.1.5 rdr le0 0/0 -> range 192.168.1.1 - 192.168.1.5 .fi .PP If there are only two addresses to split the packets across, the recommended method is to use a comma (",") like this: .nf rdr le0 0/0 -> 192.168.1.1,192.168.1.2 .fi .PP If there is a large group of destination addresses that are somewhat disjoint in nature, we can cycle through them using a .B round-robin technique like this: .nf rdr le0 0/0 -> 192.168.1.1,192.168.1.2 round-robin rdr le0 0/0 -> 192.168.1.5,192.168.1.7 round-robin rdr le0 0/0 -> 192.168.1.9 round-robin .fi .PP If there are a large number of redirect rules and hosts being targetted then it may be desirable to have all those from a single source address be targetted at the same destination address. To achieve this, the word .B sticky is appended to the rule like this: .nf rdr le0 0/0 -> 192.168.1.1,192.168.1.2 sticky rdr le0 0/0 -> 192.168.1.5,192.168.1.7 round-robin sticky rdr le0 0/0 -> 192.168.1.9 round-robin sticky .fi .PP The .B sticky feature can only be combined with .B round-robin and the use of comma. .PP For TCP and UDP packets, it is possible to both match on the destiantion port number and to modify it. For example, to change the destination port from 80 to 3128, we would use a rule like this: .nf rdr de0 0/0 port 80 -> 127.0.0.1 port 3128 tcp .fi .PP If a range of ports is given on the LHS and a single port is given on the RHS, the entire range of ports is moved. For example, if we had this: .nf rdr le0 0/0 port 80-88 -> 127.0.0.1 port 3128 tcp .fi .PP then port 80 would become 3128, port 81 would become 3129, etc. If we want to redirect a number of different pots to just a single port, an equals sign ("=") is placed before the port number on the RHS like this: .nf rdr le0 0/0 port 80-88 -> 127.0.0.1 port = 3128 tcp .fi .PP In this case, port 80 goes to 3128, port 81 to 3128, etc. .PP As with .B map rules, it is possible to manually set a timeout using the .B age option, like this: .nf rdr le0 0/0 port 53 -> 127.0.0.1 port 10053 udp age 5/5 .fi .PP The use of proxies is not restricted to .B map rules and outbound sessions. Proxies can also be used with redirect rules, although the syntax is slightly different: .nf rdr ge0 0/0 port 21 -> 127.0.0.1 port 21 tcp proxy ftp .fi .PP For .B rdr rules, the interfaces supplied are in the same order as .B map rules - input first, then output. In situations where the outgoing interface is not certain, it is also possible to use a wildcard ("*") to effect a match on any interface. .nf rdr le0,* 0/0 -> 192.168.1.0 .fi .PP A single rule, with as many options set as possible would look something like this: .nf rdr le0,ppp0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp round-robin frag age 40/40 sticky mssclamp 1000 tag tagged .fi .SH REWRITING SOURCE AND DESTINATION .PP Whilst the above two commands provide a lot of flexibility in changing addressing fields in packets, often it can be of benefit to translate \fIboth\fP source \fBand\fR destination at the same time or to change the source address on input or the destination address on output. Doing all of these things can be accomplished using .B rewrite NAT rules. .PP A .B rewrite rule requires the same level of packet matching as before, protocol and source/destination information but in addition allows either .B in or .B out to be specified like this: .nf rewrite in on ppp0 proto tcp from any to any port = 80 -> src 0/0 dst 127.0.0.1,3128; rewrite out on ppp0 from any to any -> src 0/32 dst 10.1.1.0/24; .fi .PP On the RHS we can specify both new source and destination information to place into the packet being sent out. As with other rules used in \fBipnat.conf\fR, there are shortcuts syntaxes available to use the original address information (\fB0/0\fR) and the address associated with the network interface (\fB0/32\fR.) For TCP and UDP, both address and port information can be changed. At present it is only possible to specify either a range of port numbers to be used (\fBX-Y\fR) or a single port number (\fB= X\fR) as follows: .nf rewrite in on le0 proto tcp from any to any port = 80 -> src 0/0,2000-20000 dst 127.0.0.1,port = 3128; .fi .PP There are four fields that are stepped through in enumerating the number space available for creating a new destination: .LP source address .LP source port .LP destination address .LP destination port .PP If one of these happens to be a static then it will be skipped and the next one incremented. As an example: .nf rewrite out on le0 proto tcp from any to any port = 80 -> src 1.0.0.0/8,5000-5999 dst 2.0.0.0/24,6000-6999; .fi .PP The translated packets would be: .LP 1st src=1.0.0.1,5000 dst=2.0.0.1,6000 .LP 2nd src=1.0.0.2,5000 dst=2.0.0.1,6000 .LP 3rd src=1.0.0.2,5001 dst=2.0.0.1,6000 .LP 4th src=1.0.0.2,5001 dst=2.0.0.2,6000 .LP 5th src=1.0.0.2,5001 dst=2.0.0.2,6001 .LP 6th src=1.0.0.3,5001 dst=2.0.0.2,6001 .PP and so on. .PP As with .B map rules, it is possible to specify a range of addresses by including the word \fIrange\fR before the addresses: .nf rewrite from any to any port = 80 -> src 1.1.2.3 - 1.1.2.6 dst 2.2.3.4 - 2.2.3.6; .fi .SH DIVERTING PACKETS .PP If you'd like to send packets to a UDP socket rather than just another computer to be decapsulated, this can be achieved using a .B divert rule. .PP Divert rules can be be used with both inbound and outbound packet matching however the rule .B must specify host addresses for the outer packet, not ranges of addresses or netmasks, just single addresses. Additionally the syntax must supply required information for UDP. An example of what a divert rule looks ike is as follows: .nf divert in on le0 proto udp from any to any port = 53 -> src 192.1.1.1,54 dst 192.168.1.22.1,5300; .fi .PP On the LHS is a normal set of matching capabilities but on the RHS it is a requirement to specify both the source and destination addresses and ports. .PP As this feature is intended to be used with targetting packets at sockets and not IPFilter running on other systems, there is no rule provided to \fIundivert\fR packets. .TP .B NOTE: Diverted packets \fImay\fP be fragmented if the addition of the encapsulating IP header plus UDP header causes the packet to exceed the size allowed by the outbound network interface. At present it is not possible to cause Path MTU discovery to happen as this feature is intended to be transparent to both endpoints. .B Path MTU Discovery If Path MTU discovery is being used and the "do not fragment" flag is set in packets to be encapsulated, an ICMP error message will be sent back to the sender if the new packet would need to be fragmented. .SH COMMON OPTIONS This section deals with options that are available with all rules. .TP .B purge When the purge keyword is added to the end of a NAT rule, it will cause all of the active NAT sessions to be removed when the rule is removed as an individual operation. If all of the NAT rules are flushed out, it is expected that the operator will similarly flush the NAT table and thus NAT sessions are not removed when the NAT rules are flushed out. .SH RULE ORDERING .PP .B NOTE: Rules in .B ipnat.conf are read in sequentially as listed and loaded into the kernel in this fashion .B BUT packet matching is done on \fBnetmask\fR, going from 32 down to 0. If a rule uses .B pool or .B hash to reference a set of addresses or networks, the netmask value for these fields is considered to be "0". So if your .B ipnat.conf has the following rules: .nf rdr le0 192.0.0.0/8 port 80 -> 127.0.0.1 3132 tcp rdr le0 192.2.0.0/16 port 80 -> 127.0.0.1 3131 tcp rdr le0 from any to pool/100 port 80 -> 127.0.0.1 port 3130 tcp rdr le0 192.2.2.0/24 port 80 -> 127.0.0.1 3129 tcp rdr le0 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp .fi .PP then the rule with 192.2.2.1 will match \fBfirst\fR, regardless of where it appears in the ordering of the above rules. In fact, the order in which they would be used to match a packet is: .nf rdr le0 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp rdr le0 192.2.2.0/24 port 80 -> 127.0.0.1 3129 tcp rdr le0 192.2.0.0/16 port 80 -> 127.0.0.1 3131 tcp rdr le0 192.0.0.0/8 port 80 -> 127.0.0.1 3132 tcp rdr le0 from any to pool/100 port 80 -> 127.0.0.1 port 3130 tcp .fi .PP where the first line is actually a /32. .PP If your .B ipnat.conf file has entries with matching target fields (source address for .B map rules and destination address for .B rdr rules), then the ordering in the .B ipnat.conf file does matter. So if you had the following: .nf rdr le0 from 1.1.0.0/16 to 192.2.2.1 port 80 -> 127.0.0.1 3129 tcp rdr le0 from 1.1.1.0/24 to 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp .fi .PP Then no packets will match the 2nd rule, they'll all match the first. .SH IPv6 .PP In all of the examples above, where an IPv4 address is present, an IPv6 address can also be used. All rules must use either IPv4 addresses with both halves of the NAT rule or IPv6 addresses for both halves. Mixing IPv6 addresses with IPv4 addresses, in a single rule, will result in an error. .PP For shorthand notations such as "0/32", the equivalent for IPv6 is "0/128". IPFilter will treat any netmask greater than 32 as an implicit direction that the address should be IPv6, not IPv4. To be unambiguous with 0/0, for IPv6 use ::0/0. .SH KERNEL PROXIES .PP IP Filter comes with a few, simple, proxies built into the code that is loaded into the kernel to allow secondary channels to be opened without forcing the packets through a user program. The current state of the proxies is listed below, as one of three states: .HP Aging - protocol is roughly understood from the time at which the proxy was written but it is not well tested or maintained; .HP Developmental - basic functionality exists, works most of the time but may be problematic in extended real use; .HP Experimental - rough support for the protocol at best, may or may not work as testing has been at best sporadic, possible large scale changes to the code in order to properly support the protocol. .HP Mature - well tested, protocol is properly understood by the proxy; .PP The currently compiled in proxy list is as follows: .TP FTP - Mature (map ... proxy port ftp ftp/tcp) .TP IRC - Experimental (proxy port 6667 irc/tcp) .TP rpcbind - Experimental .TP PPTP - Experimental .TP H.323 - Experimental (map ... proxy port 1720 h323/tcp) .TP Real Audio (PNA) - Aging .TP DNS - Developmental (map ... proxy port 53 dns/udp { block .cnn.com; }) .TP IPsec - Developmental (map ... proxy port 500 ipsec/tcp) .TP netbios - Experimental .TP R-command - Mature (map ... proxy port shell rcmd/tcp) .SH KERNEL PROXIES .SH FILES /dev/ipnat .br /etc/protocols .br /etc/services .br /etc/hosts .SH SEE ALSO ipnat(4), hosts(5), ipf(5), services(5), ipf(8), ipnat(8) diff --git a/sbin/ipf/ipnat/ipnat.c b/sbin/ipf/ipnat/ipnat.c index 54c770e1db26..53fdcfe9c993 100644 --- a/sbin/ipf/ipnat/ipnat.c +++ b/sbin/ipf/ipnat/ipnat.c @@ -1,833 +1,833 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) */ #include #include #include #include #include #if !defined(__SVR4) #include #else #include #endif #include #include #include #include #include #include #define _KERNEL #include #undef _KERNEL #include #include #if defined(sun) && defined(__SVR4) # include # include #endif #include #include #include #include #include #include #include #include #include #include # include #include "ipf.h" #include "netinet/ipl.h" #include "kmem.h" # define STRERROR(x) strerror(x) #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #if SOLARIS #define bzero(a,b) memset(a,0,b) #endif int use_inet6 = 0; extern char *optarg; void dostats(int, natstat_t *, int, int, int *); void dotable(natstat_t *, int, int, int, char *); void flushtable(int, int, int *); void usage(char *); int main(int, char*[]); void showhostmap(natstat_t *nsp); void natstat_dead(natstat_t *, char *); void dostats_live(int, natstat_t *, int, int *); void showhostmap_dead(natstat_t *); void showhostmap_live(int, natstat_t *); void dostats_dead(natstat_t *, int, int *); int nat_matcharray(nat_t *, int *); int opts; int nohdrfields = 0; wordtab_t *nat_fields = NULL; void usage(char *name) { fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name); exit(1); } int main(int argc, char *argv[]) { int fd, c, mode, *natfilter; char *file, *core, *kernel; natstat_t ns, *nsp; ipfobj_t obj; fd = -1; opts = 0; nsp = &ns; file = NULL; core = NULL; kernel = NULL; mode = O_RDWR; natfilter = NULL; assigndefined(getenv("IPNAT_PREDEFINED")); while ((c = getopt(argc, argv, "CdFf:hlm:M:N:nO:prRsv")) != -1) switch (c) { case 'C' : opts |= OPT_CLEAR; break; case 'd' : opts |= OPT_DEBUG; break; case 'f' : file = optarg; break; case 'F' : opts |= OPT_FLUSH; break; case 'h' : opts |=OPT_HITS; break; case 'l' : opts |= OPT_LIST; mode = O_RDONLY; break; case 'm' : natfilter = parseipfexpr(optarg, NULL); break; case 'M' : core = optarg; break; case 'N' : kernel = optarg; break; case 'n' : 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; case 'r' : opts |= OPT_REMOVE; break; case 's' : opts |= OPT_STAT; mode = O_RDONLY; break; case 'v' : opts |= OPT_VERBOSE; break; default : 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)) { (void) setgid(getgid()); (void) setuid(getuid()); } if (!(opts & OPT_DONOTHING)) { if (((fd = open(IPNAT_NAME, mode)) == -1) && ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) { (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME, STRERROR(errno)); exit(1); } } bzero((char *)&ns, sizeof(ns)); if ((opts & OPT_DONOTHING) == 0) { if (checkrev(IPL_NAME) == -1) { fprintf(stderr, "User/kernel version check failed\n"); exit(1); } } if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) { bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_NATSTAT; obj.ipfo_size = sizeof(*nsp); obj.ipfo_ptr = (void *)nsp; if (ioctl(fd, SIOCGNATS, &obj) == -1) { ipferror(fd, "ioctl(SIOCGNATS)"); exit(1); } (void) setgid(getgid()); (void) setuid(getuid()); } else if ((kernel != NULL) || (core != NULL)) { if (openkmem(kernel, core) == -1) exit(1); natstat_dead(nsp, kernel); if (opts & (OPT_LIST|OPT_STAT)) dostats(fd, nsp, opts, 0, natfilter); exit(0); } if (opts & (OPT_FLUSH|OPT_CLEAR)) flushtable(fd, opts, natfilter); if (file) { - return 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, natfilter); - return 0; + return(0); } /* * Read NAT statistic information in using a symbol table and memory file * rather than doing ioctl's. */ void natstat_dead(natstat_t *nsp, char *kernel) { struct nlist nat_nlist[10] = { { "nat_table" }, /* 0 */ { "nat_list" }, { "maptable" }, { "ipf_nattable_sz" }, { "ipf_natrules_sz" }, { "ipf_rdrrules_sz" }, /* 5 */ { "ipf_hostmap_sz" }, { "nat_instances" }, { NULL } }; void *tables[2]; if (nlist(kernel, nat_nlist) == -1) { fprintf(stderr, "nlist error\n"); return; } /* * Normally the ioctl copies all of these values into the structure * for us, before returning it to userland, so here we must copy each * one in individually. */ kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables)); 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)); kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value, sizeof(nsp->ns_maptable)); kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value, sizeof(nsp->ns_nattab_sz)); kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value, sizeof(nsp->ns_rultab_sz)); kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value, sizeof(nsp->ns_rdrtab_sz)); kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value, sizeof(nsp->ns_hostmap_sz)); kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value, sizeof(nsp->ns_instances)); } /* * Issue an ioctl to flush either the NAT rules table or the active mapping * table or both. */ void flushtable(int fd, int opts, int *match) { int n = 0; if (opts & OPT_FLUSH) { n = 0; 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) ipferror(fd, "ioctl(SIOCCNATL)"); else printf("%d entries flushed from NAT list\n", n); } } /* * Display NAT statistics. */ void dostats_dead(natstat_t *nsp, int opts, int *filter) { nat_t *np, nat; ipnat_t ipn; int i; 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 (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; 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) showhostmap_dead(nsp); } void dotable(natstat_t *nsp, int fd, int alive, int which, char *side) { int sz, i, used, maxlen, minlen, totallen; ipftable_t table; u_int *buckets; ipfobj_t obj; sz = sizeof(*buckets) * nsp->ns_nattab_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; 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; } } else { if (kmemcpy((char *)buckets, (u_long)nsp->ns_nattab_sz, sz)) { free(buckets); return; } } minlen = nsp->ns_side[which].ns_inuse; totallen = 0; maxlen = 0; used = 0; for (i = 0; i < nsp->ns_nattab_sz; i++) { if (buckets[i] > maxlen) maxlen = buckets[i]; if (buckets[i] < minlen) minlen = buckets[i]; if (buckets[i] != 0) used++; totallen += buckets[i]; } 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(int fd, natstat_t *nsp, int opts, int alive, int *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(int fd, natstat_t *nsp, int opts, int *filter) { ipfgeniter_t iter; char buffer[2000]; ipfobj_t obj; ipnat_t *ipn; nat_t nat; int i; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_GENITER; obj.ipfo_size = sizeof(iter); obj.ipfo_ptr = &iter; iter.igi_type = IPFGENITER_IPNAT; iter.igi_nitems = 1; iter.igi_data = buffer; ipn = (ipnat_t *)buffer; /* * Show list of NAT rules and NAT sessions ? */ 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"); } i = IPFGENITER_IPNAT; (void) ioctl(fd,SIOCIPFDELTOK, &i); iter.igi_type = IPFGENITER_NAT; iter.igi_nitems = 1; iter.igi_data = &nat; while (nsp->ns_instances != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; 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); } /* * Display the active host mapping table. */ void showhostmap_dead(natstat_t *nsp) { hostmap_t hm, *hmp, **maptable; u_int hv; printf("\nList of active host mappings:\n"); maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) * nsp->ns_hostmap_sz); if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable, sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) { perror("kmemcpy (maptable)"); return; } for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) { hmp = maptable[hv]; while (hmp) { if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) { perror("kmemcpy (hostmap)"); return; } printhostmap(&hm, hv); hmp = hm.hm_next; } } free(maptable); } /* * Display the active host mapping table. */ void showhostmap_live(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; obj.ipfo_type = IPFOBJ_GENITER; obj.ipfo_size = sizeof(iter); obj.ipfo_ptr = &iter; iter.igi_type = IPFGENITER_HOSTMAP; iter.igi_nitems = 1; iter.igi_data = &hm; printf("\nList of active host mappings:\n"); while (nsp->ns_maplist != NULL) { if (ioctl(fd, SIOCGENITER, &obj) == -1) break; printhostmap(&hm, hm.hm_hv); nsp->ns_maplist = hm.hm_next; } i = IPFGENITER_HOSTMAP; (void) ioctl(fd,SIOCIPFDELTOK, &i); } int nat_matcharray(nat_t *nat, int *array) { int i, n, *x, rv, p; ipfexp_t *e; 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; 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; + return(rv); } diff --git a/sbin/ipf/ipnat/ipnat_y.y b/sbin/ipf/ipnat/ipnat_y.y index 51f13d5fc6a1..9f8eb841f7d4 100644 --- a/sbin/ipf/ipnat/ipnat_y.y +++ b/sbin/ipf/ipnat/ipnat_y.y @@ -1,1746 +1,1746 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include #include #include #include #include #if !defined(__SVR4) && !defined(__GNUC__) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipf.h" #include "netinet/ipl.h" #include "ipnat_l.h" #define YYDEBUG 1 extern void yyerror(char *); extern int yyparse(void); extern int yylex(void); extern int yydebug; extern FILE *yyin; extern int yylineNum; static ipnat_t *nattop = NULL; static ipnat_t *nat = NULL; 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(void); static void setnatproto(int); static void setmapifnames(void); static void setrdrifnames(void); static void proxy_setconfig(int); static void proxy_unsetconfig(void); static namelist_t *proxy_dns_add_pass(char *, char *); static namelist_t *proxy_dns_add_block(char *, char *); static void proxy_addconfig(char *, int, char *, namelist_t *); static void proxy_loadconfig(int, ioctlfunc_t, char *, int, char *, namelist_t *); static void proxy_loadrules(int, ioctlfunc_t, proxyrule_t *); static void setmapifnames(void); static void setrdrifnames(void); static void setifname(ipnat_t **, int, char *); static int addname(ipnat_t **, char *); %} %union { char *str; u_32_t num; struct { i6addr_t a; int f; } ipa; frentry_t fr; frtuc_t *frt; u_short port; struct { int p1; int p2; int pc; } pc; struct { 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 YY_NUMBER YY_HEX %token 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 YY_IPV6 %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE %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_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 portspec %type hexnumber compare range proto %type saddr daddr sobject dobject mapfrom rdrfrom dip %type hostname ipv4 ipaddr %type addr rhsaddr rhdaddr erhdaddr %type portstuff portpair comaports srcports dstports %type dnslines dnsline %% file: line | assign | file line | file assign | file pconf ';' ; 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; 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(); } | YY_COMMENT ; assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; } ; assigning: '=' { yyvarnext = 1; } ; xx: { newnatrule(); } ; rule: map eol | mapblock eol | redir eol | rewrite ';' | divert ';' ; no: IPNY_NO { nat->in_flags |= IPN_NO; } ; eol: | ';' ; 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 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(); } | no mapit ifnames mapfrom setproto ';' { nat->in_v[0] = ftov($4); setmapifnames(); } | 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 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 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(); } | 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 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(); } ; 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 { 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); free($4); } | IPNY_PROXY port YY_STR YY_STR '/' proto { 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); 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_pr[0] != 0 || nat->in_pr[1] != 0 || nat->in_flags & IPN_TCPUDP) yyerror("protocol set twice"); setnatproto($1); } | 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_pr[0] = 0; nat->in_pr[1] = 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_pr[0] = 0; nat->in_pr[1] = 0; } ; 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 ',' { 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); } ; port: IPNY_PORT { suggest_port = 1; } ; portspec: YY_NUMBER { if ($1 > 65535) /* Unsigned */ yyerror("invalid port number"); else $$ = $1; } | YY_STR { if (getport(NULL, $1, &($$), NULL) == -1) yyerror("invalid port number"); $$ = ntohs($$); } ; portpair: portspec { $$.p1 = $1; $$.p2 = $1; } | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; } | portspec ':' portspec { $$.p1 = $1; $$.p2 = $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_spmin = $2; } | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } ; mapit: IPNY_MAP { nat->in_redir = NAT_MAP; } | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; } ; rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; } ; mapblockit: IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; } ; mapfrom: 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 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; yyexpectaddr = 1; } ; to: IPNY_TO { yyexpectaddr = 1; } ; ifnames: ifname family { yyexpectaddr = 1; } | ifname ',' otherifname family { yyexpectaddr = 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 { setifname(&nat, 1, $1); free($1); } ; mapport: 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.p1 < 0 || $3.p1 > 65535) yyerror("invalid 1st ICMP Id number"); if ($3.p2 < 0 || $3.p2 > 65535) yyerror("invalid 2nd 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_spmin = $3.p1; nat->in_spmax = $3.p2; } ; sobject: saddr { $$ = $1; } | saddr port portstuff { nat->in_osport = $3.p1; nat->in_stop = $3.p2; nat->in_scmp = $3.pc; $$ = $1; } ; 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 { $$ = $1; } | daddr port portstuff { nat->in_odport = $3.p1; nat->in_dtop = $3.p2; nat->in_dcmp = $3.pc; $$ = $1; } ; 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; } ; slash: '/' { yyexpectaddr = 0; } ; 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: compare portspec { $$.pc = $1; $$.p1 = $2; $$.p2 = 0; } | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } ; mapoptions: rr frag age mssclamp nattag setproto purge ; rdroptions: 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; } ; frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; } ; age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; nat->in_age[1] = $2; } | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2; nat->in_age[1] = $4; } ; sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && !(nat->in_flags & IPN_SPLIT)) { FPRINTF(stderr, "'sticky' for use with round-robin/IP splitting only\n"); } else nat->in_flags |= IPN_STICKY; } ; mssclamp: | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } ; tcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); } | IPNY_UDP { setnatproto(IPPROTO_UDP); } | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; nat->in_pr[0] = 0; nat->in_pr[1] = 0; } | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; 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 { 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 != -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; if ($$ != IPPROTO_TCP && $$ != IPPROTO_UDP) suggest_port = 0; } | IPNY_TCP { $$ = IPPROTO_TCP; } | IPNY_UDP { $$ = IPPROTO_UDP; } | YY_STR { $$ = getproto($1); free($1); if ($$ == -1) yyerror("unknown protocol"); if ($$ != IPPROTO_TCP && $$ != IPPROTO_UDP) suggest_port = 0; } ; hexnumber: YY_HEX { $$ = $1; } ; hostname: YY_STR { i6addr_t addr; int family; #ifdef USE_INET6 if (nat->in_v[0] == 6) family = AF_INET6; else #endif family = AF_INET; memset(&($$), 0, sizeof($$)); memset(&addr, 0, sizeof(addr)); $$.f = family; if (gethost(family, $1, &addr) == 0) { $$.a = addr; } else { FPRINTF(stderr, "Unknown host '%s'\n", $1); } free($1); } | YY_NUMBER { memset(&($$), 0, sizeof($$)); $$.a.in4.s_addr = htonl($1); if ($$.a.in4.s_addr != 0) $$.f = AF_INET; } | ipv4 { $$ = $1; } | YY_IPV6 { memset(&($$), 0, sizeof($$)); $$.a = $1; $$.f = AF_INET6; } | YY_NUMBER YY_IPV6 { memset(&($$), 0, sizeof($$)); $$.a = $2; $$.f = AF_INET6; } ; compare: '=' { $$ = FR_EQUAL; } | YY_CMP_EQ { $$ = FR_EQUAL; } | YY_CMP_NE { $$ = FR_NEQUAL; } | YY_CMP_LT { $$ = FR_LESST; } | YY_CMP_LE { $$ = FR_LESSTE; } | YY_CMP_GT { $$ = FR_GREATERT; } | YY_CMP_GE { $$ = FR_GREATERTE; } range: YY_RANGE_OUT { $$ = FR_OUTRANGE; } | YY_RANGE_IN { $$ = FR_INRANGE; } | ':' { $$ = 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; + return(0); } 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 }, { "tcpudp", IPNY_TCPUDP }, { "to", IPNY_TO }, { "udp", IPNY_UDP }, { "-", '-' }, { "->", IPNY_TLATE }, { "eq", YY_CMP_EQ }, { "ne", YY_CMP_NE }, { "lt", YY_CMP_LT }, { "gt", YY_CMP_GT }, { "le", YY_CMP_LE }, { "ge", YY_CMP_GE }, { NULL, 0 } }; int ipnat_parsefile(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"); if (s) yydebug = atoi(s); else yydebug = 0; if (strcmp(filename, "-")) { fp = fopen(filename, "r"); if (!fp) { FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, STRERROR(errno)); - return -1; + return(-1); } } else fp = stdin; while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) ; if (fp != NULL) fclose(fp); if (rval == -1) rval = 0; else if (rval != 0) rval = 1; - return rval; + return(rval); } int ipnat_parsesome(int fd, addfunc_t addfunc, ioctlfunc_t ioctlfunc, FILE *fp) { char *s; int i; natfd = fd; parser_error = 0; nataddfunc = addfunc; natioctlfunc = ioctlfunc; if (feof(fp)) - return -1; + return(-1); i = fgetc(fp); if (i == EOF) - return -1; + return(-1); if (ungetc(i, fp) == EOF) - return -1; + return(-1); if (feof(fp)) - return -1; + return(-1); s = getenv("YYDEBUG"); if (s) yydebug = atoi(s); else yydebug = 0; yyin = fp; yyparse(); - return parser_error; + return(parser_error); } static void newnatrule(void) { ipnat_t *n; n = calloc(1, sizeof(*n)); if (n == NULL) return; if (nat == NULL) { nattop = nat = n; 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(int p) { nat->in_pr[0] = p; nat->in_pr[1] = p; switch (p) { case IPPROTO_TCP : nat->in_flags |= IPN_TCP; nat->in_flags &= ~IPN_UDP; break; case IPPROTO_UDP : nat->in_flags |= IPN_UDP; nat->in_flags &= ~IPN_TCP; break; #ifdef USE_INET6 case IPPROTO_ICMPV6 : #endif case IPPROTO_ICMP : nat->in_flags &= ~IPN_TCPUDP; if (!(nat->in_flags & IPN_ICMPQUERY) && !(nat->in_redir & NAT_DIVERTUDP)) { nat->in_dcmp = 0; nat->in_scmp = 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 : if ((nat->in_redir & NAT_MAPBLK) == 0) { nat->in_flags &= ~IPN_TCPUDP; nat->in_dcmp = 0; nat->in_scmp = 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; } int ipnat_addrule(int fd, ioctlfunc_t ioctlfunc, void *ptr) { ioctlcmd_t add, del; ipfobj_t obj; ipnat_t *ipn; ipn = ptr; bzero((char *)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = ipn->in_size; obj.ipfo_type = IPFOBJ_IPNAT; obj.ipfo_ptr = ptr; if ((opts & OPT_DONOTHING) != 0) fd = -1; if (opts & OPT_ZERORULEST) { add = SIOCZRLST; del = 0; } else if (opts & OPT_PURGE) { add = 0; del = SIOCPURGENAT; } else { add = SIOCADNAT; del = SIOCRMNAT; } if ((opts & OPT_VERBOSE) != 0) printnat(ipn, opts); if (opts & OPT_DEBUG) binprint(ipn, ipn->in_size); if ((opts & OPT_ZERORULEST) != 0) { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(zero nat rule)", ipn->in_flineno); - return ipf_perror_fd(fd, ioctlfunc, msg); + return(ipf_perror_fd(fd, ioctlfunc, msg)); } } else { PRINTF("hits %lu ", ipn->in_hits); #ifdef USE_QUAD_T PRINTF("bytes %"PRIu64" ", ipn->in_bytes[0] + ipn->in_bytes[1]); #else 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) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(delete nat rule)", ipn->in_flineno); - return ipf_perror_fd(fd, ioctlfunc, msg); + return(ipf_perror_fd(fd, ioctlfunc, msg)); } } } else { if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%d:ioctl(add/insert nat rule)", ipn->in_flineno); if (errno == EEXIST) { int strlen_msg = strlen(msg); snprintf(msg + strlen_msg, sizeof(msg) -strlen_msg, "(line %d)", ipn->in_flineno); } - return ipf_perror_fd(fd, ioctlfunc, msg); + return(ipf_perror_fd(fd, ioctlfunc, msg)); } } } - return 0; + 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(void) { 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(int proxy) { if (proxy == IPNY_DNS) { yysetfixeddict(dnswords); } } static void proxy_unsetconfig(void) { yyresetdict(); } static namelist_t * proxy_dns_add_pass(char *prefix, char *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; + return(n); } static namelist_t * proxy_dns_add_block(char *prefix, char *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; + return(n); } static void proxy_addconfig(char *proxy, int proto, char *conf, 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(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(int fd, ioctlfunc_t ioctlfunc, char *proxy, int proto, char *conf, 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]; snprintf(msg, sizeof(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(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(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; + 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; + return(pos); } diff --git a/sbin/ipf/ippool/ippool.c b/sbin/ipf/ippool/ippool.c index b339c617c3de..d5e090759057 100644 --- a/sbin/ipf/ippool/ippool.c +++ b/sbin/ipf/ippool/ippool.c @@ -1,1114 +1,1114 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include #include #include # include #include #include #include #include #include #include #include #include #include #include #include # include #include "ipf.h" #include "netinet/ipl.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" #include "netinet/ip_htable.h" #include "kmem.h" extern int ippool_yyparse(void); extern int ippool_yydebug; extern FILE *ippool_yyin; extern char *optarg; extern int lineNum; void usage(char *); int main(int, char **); int poolcommand(int, int, char *[]); int poolnodecommand(int, int, char *[]); int loadpoolfile(int, char *[], char *); int poollist(int, char *[]); void poollist_dead(int, char *, int, char *, char *); void poollist_live(int, char *, int, int); int poolflush(int, char *[]); int poolstats(int, char *[]); int gettype(char *, u_int *); int getrole(char *); int setnodeaddr(int, int, void *ptr, char *arg); void showpools_live(int, int, ipf_pool_stat_t *, char *); void showhashs_live(int, int, iphtstat_t *, char *); void showdstls_live(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(char *prog) { fprintf(stderr, "Usage:\t%s\n", prog); fprintf(stderr, "\t-a [-dnv] -m [-o ] [-t type] [-T ttl] -i [/netmask]\n"); fprintf(stderr, "\t-A [-dnv] [-m ] [-o ] [-S ] [-t ]\n"); fprintf(stderr, "\t-f [-dnuvR]\n"); fprintf(stderr, "\t-F [-dv] [-o ] [-t ]\n"); fprintf(stderr, "\t-l [-dv] [-m ] [-t ] [-o ] [-M ] [-N ]\n"); fprintf(stderr, "\t-r [-dnv] [-m ] [-o ] [-t type] -i [/netmask]\n"); fprintf(stderr, "\t-R [-dnv] [-m ] [-o ] [-t ]\n"); fprintf(stderr, "\t-s [-dtv]\n"); exit(1); } int main(int argc, char *argv[]) { int err = 1; if (argc < 2) usage(argv[0]); assigndefined(getenv("IPPOOL_PREDEFINED")); switch (getopt(argc, argv, "aAf:FlrRs")) { case 'a' : err = poolnodecommand(0, argc, argv); break; case 'A' : err = poolcommand(0, argc, argv); break; case 'f' : err = loadpoolfile(argc, argv, optarg); break; case 'F' : err = poolflush(argc, argv); break; case 'l' : err = poollist(argc, argv); break; case 'r' : err = poolnodecommand(1, argc, argv); break; case 'R' : err = poolcommand(1, argc, argv); break; case 's' : err = poolstats(argc, argv); break; default : exit(1); } if (err != 0) exit(1); - return 0; + return(0); } int poolnodecommand(int remove, int argc, char *argv[]) { int err = 0, c, ipset, role, type = IPLT_POOL, ttl = 0; char *poolname = NULL; ip_pool_node_t pnode; iphtent_t hnode; void *ptr = &pnode; ipset = 0; role = IPL_LOGIPF; bzero((char *)&pnode, sizeof(pnode)); bzero((char *)&hnode, sizeof(hnode)); while ((c = getopt(argc, argv, "di:m:no:t:T:v")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; case 'i' : if (setnodeaddr(type, role, ptr, optarg) == 0) ipset = 1; break; case 'm' : poolname = optarg; break; case 'n' : opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : if (ipset == 1) { fprintf(stderr, "cannot set role after ip address\n"); - return -1; + return(-1); } role = getrole(optarg); if (role == IPL_LOGNONE) - return -1; + return(-1); break; case 't' : if (ipset == 1) { fprintf(stderr, "cannot set type after ip address\n"); - return -1; + return(-1); } type = gettype(optarg, NULL); switch (type) { case IPLT_NONE : fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; + return(-1); case IPLT_HASH : ptr = &hnode; break; case IPLT_POOL : default : break; } break; case 'T' : if (remove == 0) { ttl = atoi(optarg); if (ttl < 0) { fprintf(stderr, "cannot set negative ttl\n"); - return -1; + return(-1); } } else { usage(argv[0]); } break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - 1 - optind > 0) usage(argv[0]); if (argv[optind] != NULL && ipset == 0) { if (setnodeaddr(type, role, ptr, argv[optind]) == 0) ipset = 1; } if (opts & OPT_DEBUG) fprintf(stderr, "poolnodecommand: opts = %#x\n", opts); if (ipset == 0) { fprintf(stderr, "no IP address given with -i\n"); - return -1; + return(-1); } if (poolname == NULL) { fprintf(stderr, "poolname not given with add/remove node\n"); - return -1; + return(-1); } 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; + return(err); } int poolcommand(int remove, int argc, char *argv[]) { int type, role, c, err; char *poolname, *typearg = NULL; iphtable_t iph; ip_pool_t pool; err = 1; role = 0; type = 0; poolname = NULL; role = IPL_LOGIPF; bzero((char *)&iph, sizeof(iph)); bzero((char *)&pool, sizeof(pool)); while ((c = getopt(argc, argv, "dm:no:S:vt:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; case 'm' : poolname = optarg; break; case 'n' : opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'o' : role = getrole(optarg); if (role == IPL_LOGNONE) { fprintf(stderr, "unknown role '%s'\n", optarg); - return -1; + return(-1); } break; case 'S' : if (remove == 0) iph.iph_seed = atoi(optarg); else usage(argv[0]); break; case 't' : type = gettype(optarg, &iph.iph_type); typearg = optarg; break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - 1 - optind > 0) usage(argv[0]); if (opts & OPT_DEBUG) fprintf(stderr, "poolcommand: opts = %#x\n", opts); if (poolname == NULL) { fprintf(stderr, "poolname not given with add/remove pool\n"); - return -1; + return(-1); } if (type == IPLT_NONE && remove == 0) { if (typearg == NULL) { fprintf(stderr, "type must be specified\n"); usage(argv[0]); } else { fprintf(stderr, "unknown type '%s'\n", typearg); } - return -1; + return(-1); } if (type == IPLT_HASH || (type == IPLT_NONE && remove == 1)) { strncpy(iph.iph_name, poolname, sizeof(iph.iph_name)); iph.iph_name[sizeof(iph.iph_name) - 1] = '\0'; iph.iph_unit = role; } if (type == IPLT_POOL || (type == IPLT_NONE && remove == 1)) { strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name)); pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0'; pool.ipo_unit = role; } if (remove == 0) { switch (type) { case IPLT_HASH : err = load_hash(&iph, NULL, ioctl); break; case IPLT_POOL : err = load_pool(&pool, ioctl); break; } } else { switch (type) { case IPLT_HASH : err = remove_hash(&iph, ioctl); break; case IPLT_POOL : err = remove_pool(&pool, ioctl); break; case IPLT_NONE : err = 1; { int err_h, err_p; err_h = remove_hash(&iph, ioctl); err_p = remove_pool(&pool, ioctl); if (err_h == 0 || err_p == 0) err = 0; } break; } } - return err; + return(err); } int loadpoolfile(int argc, char *argv[], char *infile) { int c; while ((c = getopt(argc, argv, "dnuvf:")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; ippool_yydebug++; break; case 'f' : if (loadpoolfile(argc, argv, optarg) != 0) return(-1); break; case 'n' : opts |= OPT_DONOTHING|OPT_DONTOPEN; break; case 'u' : opts |= OPT_REMOVE; break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - 1 - optind > 0) usage(argv[0]); if (opts & OPT_DEBUG) fprintf(stderr, "loadpoolfile: opts = %#x\n", opts); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); exit(1); } } if (ippool_parsefile(fd, infile, ioctl) != 0) - return -1; - return 0; + return(-1); + return(0); } int poolstats(int argc, char *argv[]) { int c, type, role; ipf_pool_stat_t plstat; ipf_dstl_stat_t dlstat; iphtstat_t htstat; iplookupop_t op; type = IPLT_ALL; role = IPL_LOGALL; bzero((char *)&op, sizeof(op)); while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; break; case 'o' : role = getrole(optarg); if (role == IPL_LOGNONE) { fprintf(stderr, "unknown role '%s'\n", optarg); - return -1; + return(-1); } break; case 't' : type = gettype(optarg, NULL); if (type != IPLT_POOL) { fprintf(stderr, "-s not supported for this type yet\n"); - return -1; + return(-1); } break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - 1 - optind > 0) usage(argv[0]); if (opts & OPT_DEBUG) fprintf(stderr, "poolstats: opts = %#x\n", opts); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); exit(1); } } if (type == IPLT_ALL || type == IPLT_POOL) { op.iplo_type = IPLT_POOL; op.iplo_struct = &plstat; op.iplo_size = sizeof(plstat); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { ipferror(fd, "ioctl(S0IOCLOOKUPSTAT)"); - return -1; + return(-1); } printf("%lu\taddress pools\n", plstat.ipls_pools); printf("%lu\taddress pool nodes\n", plstat.ipls_nodes); } } if (type == IPLT_ALL || type == IPLT_HASH) { op.iplo_type = IPLT_HASH; op.iplo_struct = &htstat; op.iplo_size = sizeof(htstat); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); - return -1; + 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) { ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); - return -1; + return(-1); } 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; + return(0); } int poolflush(int argc, char *argv[]) { int c, role, type, arg; iplookupflush_t flush; arg = IPLT_ALL; type = IPLT_ALL; role = IPL_LOGALL; while ((c = getopt(argc, argv, "do:t:v")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; break; case 'o' : role = getrole(optarg); if (role == IPL_LOGNONE) { fprintf(stderr, "unknown role '%s'\n", optarg); - return -1; + return(-1); } break; case 't' : type = gettype(optarg, NULL); if (type == IPLT_NONE) { fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; + return(-1); } break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - optind > 0) usage(argv[0]); if (opts & OPT_DEBUG) fprintf(stderr, "poolflush: opts = %#x\n", opts); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); exit(1); } } bzero((char *)&flush, sizeof(flush)); flush.iplf_type = type; flush.iplf_unit = role; flush.iplf_arg = arg; if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN))) { if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) { ipferror(fd, "ioctl(SIOCLOOKUPFLUSH)"); exit(1); } } printf("%u object%s flushed\n", flush.iplf_count, (flush.iplf_count == 1) ? "" : "s"); - return 0; + return(0); } int getrole(char *rolename) { int role; if (!strcasecmp(rolename, "ipf")) { role = IPL_LOGIPF; #if 0 } else if (!strcasecmp(rolename, "nat")) { role = IPL_LOGNAT; } else if (!strcasecmp(rolename, "state")) { role = IPL_LOGSTATE; } else if (!strcasecmp(rolename, "auth")) { role = IPL_LOGAUTH; } else if (!strcasecmp(rolename, "sync")) { role = IPL_LOGSYNC; } else if (!strcasecmp(rolename, "scan")) { role = IPL_LOGSCAN; } else if (!strcasecmp(rolename, "pool")) { role = IPL_LOGLOOKUP; } else if (!strcasecmp(rolename, "count")) { role = IPL_LOGCOUNT; #endif } else { role = IPL_LOGNONE; } - return role; + return(role); } int gettype(char *typename, u_int *minor) { int type; if (!strcasecmp(typename, "tree") || !strcasecmp(typename, "pool")) { type = IPLT_POOL; } else if (!strcasecmp(typename, "hash")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_LOOKUP; } else if (!strcasecmp(typename, "group-map")) { type = IPLT_HASH; if (minor != NULL) *minor = IPHASH_GROUPMAP; } else { type = IPLT_NONE; } - return type; + return(type); } int poollist(int argc, char *argv[]) { char *kernel, *core, *poolname; int c, role, type, live_kernel; iplookupop_t op; core = NULL; kernel = NULL; live_kernel = 1; type = IPLT_ALL; poolname = NULL; role = IPL_LOGALL; while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; break; case 'm' : poolname = optarg; break; case 'M' : live_kernel = 0; core = optarg; break; case 'N' : live_kernel = 0; kernel = optarg; break; case 'o' : role = getrole(optarg); if (role == IPL_LOGNONE) { fprintf(stderr, "unknown role '%s'\n", optarg); - return -1; + return(-1); } break; #if 0 case 'O' : /* XXX This option does not work. This function as */ /* XXX used by state and nat can be used to format */ /* XXX output especially useful for scripting. It */ /* XXX is left here with the intention of making */ /* XXX it work for the same purpose at some point. */ pool_fields = parsefields(poolfields, optarg); break; #endif case 't' : type = gettype(optarg, NULL); if (type == IPLT_NONE) { fprintf(stderr, "unknown type '%s'\n", optarg); - return -1; + return(-1); } break; case 'v' : opts |= OPT_VERBOSE; break; default : usage(argv[0]); break; /* keep compiler happy */ } if (argc - optind > 0) usage(argv[0]); if (opts & OPT_DEBUG) fprintf(stderr, "poollist: opts = %#x\n", opts); if (!(opts & (OPT_DONOTHING|OPT_DONTOPEN)) && (fd == -1)) { fd = open(IPLOOKUP_NAME, O_RDWR); if (fd == -1) { perror("open(IPLOOKUP_NAME)"); exit(1); } } bzero((char *)&op, sizeof(op)); if (poolname != NULL) { strncpy(op.iplo_name, poolname, sizeof(op.iplo_name)); op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; } op.iplo_unit = role; if (live_kernel) poollist_live(role, poolname, type, fd); else poollist_dead(role, poolname, type, kernel, core); - return 0; + return(0); } void poollist_dead(int role, char *poolname, int type, char *kernel, char *core) { iphtable_t *hptr; ip_pool_t *ptr; if (openkmem(kernel, core) == -1) exit(-1); if (type == IPLT_ALL || type == IPLT_POOL) { ip_pool_t *pools[IPL_LOGSIZE]; struct nlist names[2] = { { "ip_pool_list" } , { "" } }; if (nlist(kernel, names) != 1) return; bzero(&pools, sizeof(pools)); if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools))) return; if (role != IPL_LOGALL) { ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, poolname, opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { ptr = pools[role]; while (ptr != NULL) { ptr = printpool(ptr, kmemcpywrap, poolname, opts, pool_fields); } } role = IPL_LOGALL; } } if (type == IPLT_ALL || type == IPLT_HASH) { iphtable_t *tables[IPL_LOGSIZE]; struct nlist names[2] = { { "ipf_htables" } , { "" } }; if (nlist(kernel, names) != 1) return; bzero(&tables, sizeof(tables)); if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables))) return; if (role != IPL_LOGALL) { hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, poolname, opts, pool_fields); } } else { for (role = 0; role <= IPL_LOGMAX; role++) { hptr = tables[role]; while (hptr != NULL) { hptr = printhash(hptr, kmemcpywrap, poolname, opts, pool_fields); } } } } } void poollist_live(int role, char *poolname, int type, int fd) { ipf_pool_stat_t plstat; iplookupop_t op; int c; if (type == IPLT_ALL || type == IPLT_POOL) { op.iplo_type = IPLT_POOL; op.iplo_size = sizeof(plstat); op.iplo_struct = &plstat; 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; } showpools_live(fd, role, &plstat, poolname); } else { for (role = -1; role <= IPL_LOGMAX; role++) { op.iplo_unit = role; c = ioctl(fd, SIOCLOOKUPSTAT, &op); if (c == -1) { ipferror(fd, "ioctl(SIOCLOOKUPSTAT)"); return; } showpools_live(fd, role, &plstat, poolname); } role = IPL_LOGALL; } } if (type == IPLT_ALL || type == IPLT_HASH) { iphtstat_t htstat; op.iplo_type = IPLT_HASH; op.iplo_size = sizeof(htstat); op.iplo_struct = &htstat; 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; } showhashs_live(fd, role, &htstat, 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; } 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(int fd, int role, ipf_pool_stat_t *plstp, char *poolname) { ipflookupiter_t iter; ip_pool_t pool; 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_POOL; iter.ili_otype = IPFLOOKUPITER_LIST; iter.ili_ival = IPFGENITER_LOOKUP; iter.ili_nitems = 1; iter.ili_data = &pool; iter.ili_unit = role; *iter.ili_name = '\0'; bzero((char *)&pool, sizeof(pool)); while (plstp->ipls_list[role + 1] != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } if (((pool.ipo_flags & IPOOL_DELETE) == 0) || ((opts & OPT_DEBUG) != 0)) printpool_live(&pool, fd, poolname, opts, pool_fields); plstp->ipls_list[role + 1] = pool.ipo_next; } } void showhashs_live(int fd, int role, iphtstat_t *htstp, char *poolname) { ipflookupiter_t iter; iphtable_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_HASH; 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 (htstp->iphs_tables != NULL) { if (ioctl(fd, SIOCLOOKUPITER, &obj)) { ipferror(fd, "ioctl(SIOCLOOKUPITER)"); break; } printhash_live(&table, fd, poolname, opts, pool_fields); htstp->iphs_tables = table.iph_next; } } void showdstls_live(int fd, int 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; sa_family_t family; char *s; if (strchr(arg, ':') == NULL) { family = AF_INET; s = strchr(arg, '/'); if (s == NULL) mask.s_addr = 0xffffffff; else if (strchr(s, '.') == NULL) { if (ntomask(AF_INET, atoi(s + 1), &mask.s_addr) != 0) - return -1; + return(-1); } else { mask.s_addr = inet_addr(s + 1); } if (s != NULL) *s = '\0'; } else { family = AF_INET6; /* XXX for now we use mask for IPv6 prefix length */ /* XXX mask should be a union with prefix */ /* XXX Currently address handling is sloppy. */ if ((s = strchr(arg, '/')) == NULL) mask.s_addr = 128; else mask.s_addr = atoi(s + 1); } if (type == IPLT_POOL) { ip_pool_node_t *node = ptr; node->ipn_addr.adf_family = family; #ifdef USE_INET6 if (node->ipn_addr.adf_family == AF_INET) { #endif node->ipn_addr.adf_len = offsetof(addrfamily_t, adf_addr) + sizeof(struct in_addr); node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg); #ifdef USE_INET6 } else { node->ipn_addr.adf_len = offsetof(addrfamily_t, adf_addr) + sizeof(struct in6_addr); inet_pton(AF_INET6, arg, &node->ipn_addr.adf_addr.in6.s6_addr); } #endif 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_family = family; node->ipe_unit = role; #ifdef USE_INET6 if (node->ipe_family == AF_INET) { #endif node->ipe_addr.in4.s_addr = inet_addr(arg); node->ipe_mask.in4.s_addr = mask.s_addr; #ifdef USE_INET6 } else { inet_pton(AF_INET6, arg, &node->ipe_addr.in6.__u6_addr.__u6_addr32); node->ipe_mask.in6.__u6_addr.__u6_addr32[0] = mask.s_addr; node->ipe_mask.in6.__u6_addr.__u6_addr32[1] = node->ipe_mask.in6.__u6_addr.__u6_addr32[2] = node->ipe_mask.in6.__u6_addr.__u6_addr32[3] = 0; } #endif } - return 0; + return(0); } diff --git a/sbin/ipf/ippool/ippool_y.y b/sbin/ipf/ippool/ippool_y.y index 5ec9b6ef0083..9e01318a78c7 100644 --- a/sbin/ipf/ippool/ippool_y.y +++ b/sbin/ipf/ippool/ippool_y.y @@ -1,824 +1,824 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include #include #include #include # include #include #include #include #include #include #include #include #include #include #include #include #include "ipf.h" #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" #define YYDEBUG 1 #define YYSTACKSIZE 0x00ffffff extern int yyparse(void); extern int yydebug; 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(char *); static ip_pool_node_t *add_poolhosts(char *); static ip_pool_node_t *read_whoisfile(char *); static void setadflen(addrfamily_t *); %} %union { char *str; u_32_t num; struct in_addr ip4; struct alist_s *alist; addrfamily_t adrmsk[2]; iphtent_t *ipe; ip_pool_node_t *ipp; ipf_dstnode_t *ipd; addrfamily_t ipa; i6addr_t ip6; } %token YY_NUMBER YY_HEX %token YY_STR %token 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 IPT_POLICY %token IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN %token IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION %token IPT_WHOIS IPT_FILE %type role table inout unit dstopts weighting %type ipftree range addrlist %type addrmask %type ipfgroup ipfhash hashlist hashentry %type groupentry setgrouplist grouplist %type ipaddr mask %type ipv4 %type number setgroup name %type dstentry dstentries dstlist %% file: line | assign | file line | file assign ; 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 { 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 { 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: ';' ; assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; } ; assigning: '=' { yyvarnext = 1; } ; 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'; } ; groupmap: IPT_GROUPMAP inout { bzero((char *)&ipht, sizeof(ipht)); bzero((char *)&iphte, sizeof(iphte)); *ipht.iph_name = '\0'; ipht.iph_unit = IPHASH_GROUPMAP; ipht.iph_flags = $2; } ; inout: IPT_IN { $$ = FR_INQUE; } | IPT_OUT { $$ = FR_OUTQUE; } ; 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: IPT_TYPE '=' IPT_TREE number start addrlist end { strncpy(iplo.ipo_name, $4, sizeof(iplo.ipo_name)); $$ = $6; } ; ipfhash: IPT_TYPE '=' IPT_HASH number hashopts start hashlist end { strncpy(ipht.iph_name, $4, sizeof(ipht.iph_name)); $$ = $7; } ; ipfgroup: setgroup hashopts start grouplist end { iphtent_t *e; for (e = $4; e != NULL; e = e->ipe_next) if (e->ipe_group[0] == '\0') strncpy(e->ipe_group, $1, FR_GROUPLEN); $$ = $4; free($1); } | hashopts start setgrouplist end { $$ = $3; } ; number: IPT_NUM '=' YY_NUMBER { snprintf(poolname, sizeof(poolname), "%u", $3); $$ = poolname; } | IPT_NAME '=' YY_STR { strncpy(poolname, $3, FR_GROUPLEN); poolname[FR_GROUPLEN-1]='\0'; free($3); $$ = poolname; } | { $$ = ""; } ; 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]; snprintf(tmp, sizeof(tmp), "%u", $3); $$ = strdup(tmp); } ; hashopts: | size | seed | size seed ; addrlist: ';' { $$ = NULL; } | range next addrlist { $$ = $1; while ($1->ipn_next != NULL) $1 = $1->ipn_next; $1->ipn_next = $3; } | range next { $$ = $1; } ; grouplist: ';' { $$ = NULL; } | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); $$->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)); $$->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); } ; setgrouplist: ';' { $$ = NULL; } | groupentry next { $$ = $1; } | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } ; groupentry: addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); $$->ipe_addr = $1[0].adf_addr; $$->ipe_mask = $1[1].adf_addr; strncpy($$->ipe_group, $3, FR_GROUPLEN); #ifdef USE_INET6 if (use_inet6) $$->ipe_family = AF_INET6; else #endif $$->ipe_family = AF_INET; free($3); } ; range: addrmask { $$ = calloc(1, sizeof(*$$)); $$->ipn_info = 0; $$->ipn_addr = $1[0]; $$->ipn_mask = $1[1]; #ifdef USE_INET6 if (use_inet6) $$->ipn_addr.adf_family = AF_INET6; else #endif $$->ipn_addr.adf_family = AF_INET; } | '!' addrmask { $$ = calloc(1, sizeof(*$$)); $$->ipn_info = 1; $$->ipn_addr = $2[0]; $$->ipn_mask = $2[1]; #ifdef USE_INET6 if (use_inet6) $$->ipn_addr.adf_family = AF_INET6; else #endif $$->ipn_addr.adf_family = AF_INET; } | YY_STR { $$ = add_poolhosts($1); free($1); } | IPT_WHOIS IPT_FILE YY_STR { $$ = read_whoisfile($3); free($3); } ; hashlist: ';' { $$ = NULL; } | hashentry next { $$ = $1; } | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } ; hashentry: 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; setadflen(&$$[0]); $$[1] = $3; $$[1].adf_len = $$[0].adf_len; } | 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 { $$.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; } ; 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; } ; seed: IPT_SEED '=' YY_NUMBER { ipht.iph_seed = $3; } ; 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; + return(0); } $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; $$.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]; snprintf(name, sizeof(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[] = { { "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 } }; int ippool_parsefile(int fd, char *filename, ioctlfunc_t iocfunc) { FILE *fp = NULL; char *s; yylineNum = 1; (void) yysettab(yywords); s = getenv("YYDEBUG"); if (s) yydebug = atoi(s); else yydebug = 0; if (strcmp(filename, "-")) { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "fopen(%s) failed: %s\n", filename, STRERROR(errno)); - return -1; + return(-1); } } else fp = stdin; while (ippool_parsesome(fd, fp, iocfunc) == 1) ; if (fp != NULL) fclose(fp); - return 0; + return(0); } int ippool_parsesome(int fd, FILE *fp, ioctlfunc_t iocfunc) { char *s; int i; poolioctl = iocfunc; if (feof(fp)) - return 0; + return(0); i = fgetc(fp); if (i == EOF) - return 0; + return(0); if (ungetc(i, fp) == EOF) - return 0; + return(0); if (feof(fp)) - return 0; + return(0); s = getenv("YYDEBUG"); if (s) yydebug = atoi(s); else yydebug = 0; yyin = fp; yyparse(); - return 1; + return(1); } static iphtent_t * add_htablehosts(char *url) { iphtent_t *htop, *hbot, *h; alist_t *a, *hlist; if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) { hlist = load_url(url); } else { use_inet6 = 0; hlist = calloc(1, sizeof(*hlist)); if (hlist == NULL) - return NULL; + return(NULL); if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); } } hbot = NULL; htop = NULL; for (a = hlist; a != NULL; a = a->al_next) { h = calloc(1, sizeof(*h)); if (h == NULL) break; 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; else htop = h; hbot = h; } alist_free(hlist); - return htop; + return(htop); } static ip_pool_node_t * add_poolhosts(char *url) { ip_pool_node_t *ptop, *pbot, *p; alist_t *a, *hlist; if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) { hlist = load_url(url); } else { use_inet6 = 0; hlist = calloc(1, sizeof(*hlist)); if (hlist == NULL) - return NULL; + return(NULL); if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) { yyerror("Unknown hostname"); } } pbot = NULL; ptop = NULL; for (a = hlist; a != NULL; a = a->al_next) { p = calloc(1, sizeof(*p)); if (p == NULL) break; p->ipn_mask.adf_addr = a->al_i6mask; 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; p->ipn_mask.adf_len = p->ipn_addr.adf_len; if (pbot != NULL) pbot->ipn_next = p; else ptop = p; pbot = p; } alist_free(hlist); - return ptop; + return(ptop); } ip_pool_node_t * read_whoisfile(char *file) { ip_pool_node_t *ntop, *ipn, node, *last; char line[1024]; FILE *fp; fp = fopen(file, "r"); if (fp == NULL) - return 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; + return(ntop); } static void setadflen(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/sbin/ipf/ipscan/ipscan_y.y b/sbin/ipf/ipscan/ipscan_y.y index 134dbc70f048..21d1b15aed70 100644 --- a/sbin/ipf/ipscan/ipscan_y.y +++ b/sbin/ipf/ipscan/ipscan_y.y @@ -1,569 +1,569 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include #include #include "ipf.h" #include "opts.h" #include "kmem.h" #include "ipscan_l.h" #include "netinet/ip_scan.h" #include #define YYDEBUG 1 extern char *optarg; extern void yyerror(char *); extern int yyparse(void); extern int yylex(void); extern int yydebug; extern FILE *yyin; extern int yylineNum; extern void printbuf(char *, int, int); void printent(ipscan_t *); void showlist(void); int getportnum(char *); struct in_addr gethostip(char *); struct in_addr combine(int, int, int, int); char **makepair(char *, char *); void addtag(char *, char **, char **, struct action *); int cram(char *, char *); void usage(char *); int main(int, char **); int opts = 0; int fd = -1; %} %union { char *str; char **astr; u_32_t num; struct in_addr ipa; struct action act; union i6addr ip6; } %type tag %type action redirect result %type ipaddr %type portnum %type matchup onehalf twohalves %token YY_NUMBER YY_HEX %token 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 YY_IPV6 %token IPSL_START IPSL_STARTGROUP IPSL_CONTENT %token IPSL_CLOSE IPSL_TRACK IPSL_EOF IPSL_REDIRECT IPSL_ELSE %% file: line ';' | assign ';' | file line ';' | file assign ';' | YY_COMMENT ; line: IPSL_START dline | IPSL_STARTGROUP gline | IPSL_CONTENT oline ; dline: cline { resetlexer(); } | sline { resetlexer(); } | csline { resetlexer(); } ; gline: YY_STR ':' glist '=' action ; oline: cline | sline | csline ; assign: YY_STR assigning YY_STR { set_variable($1, $3); resetlexer(); free($1); free($3); yyvarnext = 0; } ; assigning: '=' { yyvarnext = 1; } ; cline: tag ':' matchup '=' action { addtag($1, $3, NULL, &$5); } ; sline: tag ':' '(' ')' ',' matchup '=' action { addtag($1, NULL, $6, &$8); } ; csline: tag ':' matchup ',' matchup '=' action { addtag($1, $3, $5, &$7); } ; glist: YY_STR | glist ',' YY_STR ; tag: YY_STR { $$ = $1; } ; matchup: onehalf { $$ = $1; } | twohalves { $$ = $1; } ; action: result { $$.act_val = $1.act_val; $$.act_ip = $1.act_ip; $$.act_port = $1.act_port; } | result IPSL_ELSE result { $$.act_val = $1.act_val; $$.act_else = $3.act_val; if ($1.act_val == IPSL_REDIRECT) { $$.act_ip = $1.act_ip; $$.act_port = $1.act_port; } if ($3.act_val == IPSL_REDIRECT) { $$.act_eip = $3.act_eip; $$.act_eport = $3.act_eport; } } result: IPSL_CLOSE { $$.act_val = IPSL_CLOSE; } | IPSL_TRACK { $$.act_val = IPSL_TRACK; } | redirect { $$.act_val = IPSL_REDIRECT; $$.act_ip = $1.act_ip; $$.act_port = $1.act_port; } ; onehalf: '(' YY_STR ')' { $$ = makepair($2, NULL); } ; twohalves: '(' YY_STR ',' YY_STR ')' { $$ = makepair($2, $4); } ; redirect: IPSL_REDIRECT '(' ipaddr ')' { $$.act_ip = $3; $$.act_port = 0; } | IPSL_REDIRECT '(' ipaddr ',' portnum ')' { $$.act_ip = $3; $$.act_port = $5; } ; ipaddr: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER { $$ = combine($1,$3,$5,$7); } | YY_STR { $$ = gethostip($1); free($1); } ; portnum: YY_NUMBER { $$ = htons($1); } | YY_STR { $$ = getportnum($1); free($1); } ; %% static struct wordtab yywords[] = { { "close", IPSL_CLOSE }, { "content", IPSL_CONTENT }, { "else", IPSL_ELSE }, { "start-group", IPSL_STARTGROUP }, { "redirect", IPSL_REDIRECT }, { "start", IPSL_START }, { "track", IPSL_TRACK }, { NULL, 0 } }; int cram(char *dst, char *src) { char c, *s, *t, *u; int i, j, k; c = *src; s = src + 1; t = strchr(s, c); *t = '\0'; for (u = dst, i = 0; (i <= ISC_TLEN) && (s < t); ) { c = *s++; if (c == '\\') { if (s >= t) break; j = k = 0; do { c = *s++; if (j && (!ISDIGIT(c) || (c > '7') || (k >= 248))) { *u++ = k, i++; j = k = 0; s--; break; } i++; if (ISALPHA(c) || (c > '7')) { switch (c) { case 'n' : *u++ = '\n'; break; case 'r' : *u++ = '\r'; break; case 't' : *u++ = '\t'; break; default : *u++ = c; break; } } else if (ISDIGIT(c)) { j = 1; k <<= 3; k |= (c - '0'); i--; } else *u++ = c; } while ((i <= ISC_TLEN) && (s <= t) && (j > 0)); } else *u++ = c, i++; } - return i; + return(i); } void printent(ipscan_t *isc) { char buf[ISC_TLEN+1]; u_char *u; int i, j; buf[ISC_TLEN] = '\0'; bcopy(isc->ipsc_ctxt, buf, ISC_TLEN); printf("%s : (\"", isc->ipsc_tag); printbuf(isc->ipsc_ctxt, isc->ipsc_clen, 0); bcopy(isc->ipsc_cmsk, buf, ISC_TLEN); printf("\", \"%s\"), (\"", buf); printbuf(isc->ipsc_stxt, isc->ipsc_slen, 0); bcopy(isc->ipsc_smsk, buf, ISC_TLEN); printf("\", \"%s\") = ", buf); switch (isc->ipsc_action) { case ISC_A_TRACK : printf("track"); break; case ISC_A_REDIRECT : printf("redirect"); printf("(%s", inet_ntoa(isc->ipsc_ip)); if (isc->ipsc_port) printf(",%d", isc->ipsc_port); printf(")"); break; case ISC_A_CLOSE : printf("close"); break; default : break; } if (isc->ipsc_else != ISC_A_NONE) { printf(" else "); switch (isc->ipsc_else) { case ISC_A_TRACK : printf("track"); break; case ISC_A_REDIRECT : printf("redirect"); printf("(%s", inet_ntoa(isc->ipsc_eip)); if (isc->ipsc_eport) printf(",%d", isc->ipsc_eport); printf(")"); break; case ISC_A_CLOSE : printf("close"); break; default : break; } } printf("\n"); if (opts & OPT_DEBUG) { for (u = (u_char *)isc, i = sizeof(*isc); i; ) { printf("#"); for (j = 32; (j > 0) && (i > 0); j--, i--) printf("%s%02x", (j & 7) ? "" : " ", *u++); printf("\n"); } } if (opts & OPT_VERBOSE) { printf("# hits %d active %d fref %d sref %d\n", isc->ipsc_hits, isc->ipsc_active, isc->ipsc_fref, isc->ipsc_sref); } } void addtag(char *tstr, char **cp, char **sp, struct action *act) { ipscan_t isc, *iscp; bzero((char *)&isc, sizeof(isc)); strncpy(isc.ipsc_tag, tstr, sizeof(isc.ipsc_tag)); isc.ipsc_tag[sizeof(isc.ipsc_tag) - 1] = '\0'; if (cp) { isc.ipsc_clen = cram(isc.ipsc_ctxt, cp[0]); if (cp[1]) { if (cram(isc.ipsc_cmsk, cp[1]) != isc.ipsc_clen) { fprintf(stderr, "client text/mask strings different length\n"); return; } } } if (sp) { isc.ipsc_slen = cram(isc.ipsc_stxt, sp[0]); if (sp[1]) { if (cram(isc.ipsc_smsk, sp[1]) != isc.ipsc_slen) { fprintf(stderr, "server text/mask strings different length\n"); return; } } } if (act->act_val == IPSL_CLOSE) { isc.ipsc_action = ISC_A_CLOSE; } else if (act->act_val == IPSL_TRACK) { isc.ipsc_action = ISC_A_TRACK; } else if (act->act_val == IPSL_REDIRECT) { isc.ipsc_action = ISC_A_REDIRECT; isc.ipsc_ip = act->act_ip; isc.ipsc_port = act->act_port; fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1); } if (act->act_else == IPSL_CLOSE) { isc.ipsc_else = ISC_A_CLOSE; } else if (act->act_else == IPSL_TRACK) { isc.ipsc_else = ISC_A_TRACK; } else if (act->act_else == IPSL_REDIRECT) { isc.ipsc_else = ISC_A_REDIRECT; isc.ipsc_eip = act->act_eip; isc.ipsc_eport = act->act_eport; fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1); } if (!(opts & OPT_DONOTHING)) { iscp = &isc; if (opts & OPT_REMOVE) { if (ioctl(fd, SIOCRMSCA, &iscp) == -1) perror("SIOCADSCA"); } else { if (ioctl(fd, SIOCADSCA, &iscp) == -1) perror("SIOCADSCA"); } } if (opts & OPT_VERBOSE) printent(&isc); } char ** makepair(char *s1, char *s2) { char **a; a = malloc(sizeof(char *) * 2); a[0] = s1; a[1] = s2; - return a; + return(a); } struct in_addr combine(int a1, int a2, int a3, int a4) { struct in_addr in; a1 &= 0xff; in.s_addr = a1 << 24; a2 &= 0xff; in.s_addr |= (a2 << 16); a3 &= 0xff; in.s_addr |= (a3 << 8); a4 &= 0xff; in.s_addr |= a4; in.s_addr = htonl(in.s_addr); - return in; + return(in); } struct in_addr gethostip(char *host) { struct hostent *hp; struct in_addr in; in.s_addr = 0; hp = gethostbyname(host); if (!hp) - return in; + return(in); bcopy(hp->h_addr, (char *)&in, sizeof(in)); - return in; + return(in); } int getportnum(char *port) { struct servent *s; s = getservbyname(port, "tcp"); if (s == NULL) - return -1; - return s->s_port; + return(-1); + return(s->s_port); } void showlist(void) { ipscanstat_t ipsc, *ipscp = &ipsc; ipscan_t isc; if (ioctl(fd, SIOCGSCST, &ipscp) == -1) perror("ioctl(SIOCGSCST)"); else if (opts & OPT_SHOWLIST) { while (ipsc.iscs_list != NULL) { if (kmemcpy((char *)&isc, (u_long)ipsc.iscs_list, sizeof(isc)) == -1) { perror("kmemcpy"); break; } else { printent(&isc); ipsc.iscs_list = isc.ipsc_next; } } } else { printf("scan entries loaded\t%d\n", ipsc.iscs_entries); printf("scan entries matches\t%ld\n", ipsc.iscs_acted); printf("negative matches\t%ld\n", ipsc.iscs_else); } } void usage(char *prog) { fprintf(stderr, "Usage:\t%s [-dnrv] -f \n", prog); fprintf(stderr, "\t%s [-dlv]\n", prog); exit(1); } int main(int argc, char *argv[]) { FILE *fp = NULL; int c; (void) yysettab(yywords); if (argc < 2) usage(argv[0]); while ((c = getopt(argc, argv, "df:lnrsv")) != -1) switch (c) { case 'd' : opts |= OPT_DEBUG; yydebug++; break; case 'f' : if (!strcmp(optarg, "-")) fp = stdin; else { fp = fopen(optarg, "r"); if (!fp) { perror("open"); exit(1); } } yyin = fp; break; case 'l' : opts |= OPT_SHOWLIST; break; case 'n' : opts |= OPT_DONOTHING; break; case 'r' : opts |= OPT_REMOVE; break; case 's' : opts |= OPT_STAT; break; case 'v' : opts |= OPT_VERBOSE; break; } if (!(opts & OPT_DONOTHING)) { fd = open(IPL_SCAN, O_RDWR); if (fd == -1) { perror("open(IPL_SCAN)"); exit(1); } } if (fp != NULL) { yylineNum = 1; while (!feof(fp)) yyparse(); fclose(fp); exit(0); } if (opts & (OPT_SHOWLIST|OPT_STAT)) { showlist(); exit(0); } exit(1); } diff --git a/sbin/ipf/ipsend/44arp.c b/sbin/ipf/ipsend/44arp.c index 9f82ed6a741d..f949c77614cc 100644 --- a/sbin/ipf/ipsend/44arp.c +++ b/sbin/ipf/ipsend/44arp.c @@ -1,116 +1,116 @@ /* $FreeBSD$ */ /* * Based upon 4.4BSD's /usr/sbin/arp */ #include #include #include #include #include #include #include # include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" #include "iplang/iplang.h" /* * lookup host and return * its IP address in address * (4 bytes) */ int resolve(char *host, char *address) { struct hostent *hp; u_long add; add = inet_addr(host); if (add == -1) { if (!(hp = gethostbyname(host))) { fprintf(stderr, "unknown host: %s\n", host); - return -1; + return(-1); } bcopy((char *)hp->h_addr, (char *)address, 4); - return 0; + return(0); } bcopy((char*)&add, address, 4); - return 0; + return(0); } int arp(char *addr, char *eaddr) { int mib[6]; size_t needed; char *lim, *buf, *next; struct rt_msghdr *rtm; struct sockaddr_in *sin; struct sockaddr_dl *sdl; #ifdef IPSEND if (arp_getipv4(addr, ether) == 0) - return 0; + return(0); #endif if (!addr) - return -1; + return(-1); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_FLAGS; #ifdef RTF_LLINFO mib[5] = RTF_LLINFO; #else mib[5] = 0; #endif if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) { perror("route-sysctl-estimate"); exit(-1); } if ((buf = malloc(needed)) == NULL) { perror("malloc"); exit(-1); } if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) { perror("actual retrieval of routing table"); exit(-1); } lim = buf + needed; for (next = buf; next < lim; next += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)next; sin = (struct sockaddr_in *)(rtm + 1); sdl = (struct sockaddr_dl *)(sin + 1); if (!bcmp(addr, (char *)&sin->sin_addr, sizeof(struct in_addr))) { bcopy(LLADDR(sdl), eaddr, sdl->sdl_alen); - return 0; + return(0); } } - return -1; + return(-1); } diff --git a/sbin/ipf/ipsend/arp.c b/sbin/ipf/ipsend/arp.c index e6bbedb9ec50..82df2e694e17 100644 --- a/sbin/ipf/ipsend/arp.c +++ b/sbin/ipf/ipsend/arp.c @@ -1,134 +1,134 @@ /* $FreeBSD$ */ /* * arp.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include # include #include #include #include #include #include # include #include #include #include #include #include #include #include #include "ipsend.h" #include "iplang/iplang.h" /* * lookup host and return * its IP address in address * (4 bytes) */ int resolve(char *host, char *address) { struct hostent *hp; u_long add; add = inet_addr(host); if (add == -1) { if (!(hp = gethostbyname(host))) { fprintf(stderr, "unknown host: %s\n", host); - return -1; + return(-1); } bcopy((char *)hp->h_addr, (char *)address, 4); - return 0; + return(0); } bcopy((char*)&add, address, 4); - return 0; + return(0); } /* * ARP for the MAC address corresponding * to the IP address. This taken from * some BSD program, I cant remember which. */ int arp(ip, ether) char *ip; char *ether; { static int sfd = -1; static char ethersave[6], ipsave[4]; struct arpreq ar; struct sockaddr_in *sin, san; struct hostent *hp; int fd; #ifdef IPSEND if (arp_getipv4(ip, ether) == 0) - return 0; + return(0); #endif if (!bcmp(ipsave, ip, 4)) { bcopy(ethersave, ether, 6); - return 0; + return(0); } fd = -1; bzero((char *)&ar, sizeof(ar)); sin = (struct sockaddr_in *)&ar.arp_pa; sin->sin_family = AF_INET; bcopy(ip, (char *)&sin->sin_addr.s_addr, 4); if ((hp = gethostbyaddr(ip, 4, AF_INET))) # if SOLARIS && (SOLARIS2 >= 10) if (!(ether_hostton(hp->h_name, (struct ether_addr *)ether))) # else if (!(ether_hostton(hp->h_name, ether))) # endif goto savearp; if (sfd == -1) if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("arp: socket"); - return -1; + return(-1); } tryagain: if (ioctl(sfd, SIOCGARP, (caddr_t)&ar) == -1) { if (fd == -1) { bzero((char *)&san, sizeof(san)); san.sin_family = AF_INET; san.sin_port = htons(1); bcopy(ip, &san.sin_addr.s_addr, 4); fd = socket(AF_INET, SOCK_DGRAM, 0); (void) sendto(fd, ip, 4, 0, (struct sockaddr *)&san, sizeof(san)); sleep(1); (void) close(fd); goto tryagain; } fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr)); if (errno != ENXIO) perror("SIOCGARP"); - return -1; + return(-1); } if ((ar.arp_ha.sa_data[0] == 0) && (ar.arp_ha.sa_data[1] == 0) && (ar.arp_ha.sa_data[2] == 0) && (ar.arp_ha.sa_data[3] == 0) && (ar.arp_ha.sa_data[4] == 0) && (ar.arp_ha.sa_data[5] == 0)) { fprintf(stderr, "(%s):", inet_ntoa(sin->sin_addr)); - return -1; + return(-1); } bcopy(ar.arp_ha.sa_data, ether, 6); savearp: bcopy(ether, ethersave, 6); bcopy(ip, ipsave, 4); - return 0; + return(0); } diff --git a/sbin/ipf/ipsend/dlcommon.c b/sbin/ipf/ipsend/dlcommon.c index 86554660240d..d7cffeb2f38d 100644 --- a/sbin/ipf/ipsend/dlcommon.c +++ b/sbin/ipf/ipsend/dlcommon.c @@ -1,1283 +1,1283 @@ /* $FreeBSD$ */ /* * Common (shared) DLPI test routines. * Mostly pretty boring boilerplate sorta stuff. * These can be split into individual library routines later * but it's just convenient to keep them in a single file * while they're being developed. * * Not supported: * Connection Oriented stuff * QOS stuff */ /* typedef unsigned long ulong; */ #include #include #include # include #include #include #include #include "dltest.h" -#define CASERET(s) case s: return ("s") +#define CASERET(s) case s: return("s") char *dlprim(); char *dlstate(); char *dlerrno(); char *dlpromisclevel(); char *dlservicemode(); char *dlstyle(); char *dlmactype(); void dlinforeq(int fd) { dl_info_req_t info_req; struct strbuf ctl; int flags; info_req.dl_primitive = DL_INFO_REQ; ctl.maxlen = 0; ctl.len = sizeof (info_req); ctl.buf = (char *) &info_req; flags = RS_HIPRI; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlinforeq: putmsg"); } void dlinfoack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlinfoack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_INFO_ACK, dlp); if (ctl.len < sizeof (dl_info_ack_t)) err("dlinfoack: response ctl.len too short: %d", ctl.len); if (flags != RS_HIPRI) err("dlinfoack: DL_INFO_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_info_ack_t)) err("dlinfoack: short response ctl.len: %d", ctl.len); } void dlattachreq(int fd, u_long ppa) { dl_attach_req_t attach_req; struct strbuf ctl; int flags; attach_req.dl_primitive = DL_ATTACH_REQ; attach_req.dl_ppa = ppa; ctl.maxlen = 0; ctl.len = sizeof (attach_req); ctl.buf = (char *) &attach_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlattachreq: putmsg"); } void dlenabmultireq(int fd, char *addr, int length) { long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf ctl; int flags; dlp = (union DL_primitives*) buf; dlp->enabmulti_req.dl_primitive = DL_ENABMULTI_REQ; dlp->enabmulti_req.dl_addr_length = length; dlp->enabmulti_req.dl_addr_offset = sizeof (dl_enabmulti_req_t); (void) memcpy((char*)OFFADDR(buf, sizeof (dl_enabmulti_req_t)), addr, length); ctl.maxlen = 0; ctl.len = sizeof (dl_enabmulti_req_t) + length; ctl.buf = (char*) buf; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlenabmultireq: putmsg"); } void dldisabmultireq(int fd, char *addr, int length) { long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf ctl; int flags; dlp = (union DL_primitives*) buf; dlp->disabmulti_req.dl_primitive = DL_ENABMULTI_REQ; dlp->disabmulti_req.dl_addr_length = length; dlp->disabmulti_req.dl_addr_offset = sizeof (dl_disabmulti_req_t); (void) memcpy((char*)OFFADDR(buf, sizeof (dl_disabmulti_req_t)), addr, length); ctl.maxlen = 0; ctl.len = sizeof (dl_disabmulti_req_t) + length; ctl.buf = (char*) buf; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dldisabmultireq: putmsg"); } void dlpromisconreq(int fd, u_long level) { dl_promiscon_req_t promiscon_req; struct strbuf ctl; int flags; promiscon_req.dl_primitive = DL_PROMISCON_REQ; promiscon_req.dl_level = level; ctl.maxlen = 0; ctl.len = sizeof (promiscon_req); ctl.buf = (char *) &promiscon_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlpromiscon: putmsg"); } void dlpromiscoff(int fd, u_long level) { dl_promiscoff_req_t promiscoff_req; struct strbuf ctl; int flags; promiscoff_req.dl_primitive = DL_PROMISCOFF_REQ; promiscoff_req.dl_level = level; ctl.maxlen = 0; ctl.len = sizeof (promiscoff_req); ctl.buf = (char *) &promiscoff_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlpromiscoff: putmsg"); } void dlphysaddrreq(int fd, u_long addrtype) { dl_phys_addr_req_t phys_addr_req; struct strbuf ctl; int flags; phys_addr_req.dl_primitive = DL_PHYS_ADDR_REQ; phys_addr_req.dl_addr_type = addrtype; ctl.maxlen = 0; ctl.len = sizeof (phys_addr_req); ctl.buf = (char *) &phys_addr_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlphysaddrreq: putmsg"); } void dlsetphysaddrreq(int fd, char *addr, int length) { long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf ctl; int flags; dlp = (union DL_primitives*) buf; dlp->set_physaddr_req.dl_primitive = DL_ENABMULTI_REQ; dlp->set_physaddr_req.dl_addr_length = length; dlp->set_physaddr_req.dl_addr_offset = sizeof (dl_set_phys_addr_req_t); (void) memcpy((char*)OFFADDR(buf, sizeof (dl_set_phys_addr_req_t)), addr, length); ctl.maxlen = 0; ctl.len = sizeof (dl_set_phys_addr_req_t) + length; ctl.buf = (char*) buf; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlsetphysaddrreq: putmsg"); } void dldetachreq(int fd) { dl_detach_req_t detach_req; struct strbuf ctl; int flags; detach_req.dl_primitive = DL_DETACH_REQ; ctl.maxlen = 0; ctl.len = sizeof (detach_req); ctl.buf = (char *) &detach_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dldetachreq: putmsg"); } void dlbindreq(int fd, u_long sap, u_long max_conind, u_long service_mode, u_long conn_mgmt, u_long xidtest) { dl_bind_req_t bind_req; struct strbuf ctl; int flags; bind_req.dl_primitive = DL_BIND_REQ; bind_req.dl_sap = sap; bind_req.dl_max_conind = max_conind; bind_req.dl_service_mode = service_mode; bind_req.dl_conn_mgmt = conn_mgmt; bind_req.dl_xidtest_flg = xidtest; ctl.maxlen = 0; ctl.len = sizeof (bind_req); ctl.buf = (char *) &bind_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlbindreq: putmsg"); } void dlunitdatareq(int fd, u_char *addrp, int addrlen, u_long minpri, u_long maxpri, u_char *datap, int datalen) { long buf[MAXDLBUF]; union DL_primitives *dlp; struct strbuf data, ctl; dlp = (union DL_primitives*) buf; dlp->unitdata_req.dl_primitive = DL_UNITDATA_REQ; dlp->unitdata_req.dl_dest_addr_length = addrlen; dlp->unitdata_req.dl_dest_addr_offset = sizeof (dl_unitdata_req_t); dlp->unitdata_req.dl_priority.dl_min = minpri; dlp->unitdata_req.dl_priority.dl_max = maxpri; (void) memcpy(OFFADDR(dlp, sizeof (dl_unitdata_req_t)), addrp, addrlen); ctl.maxlen = 0; ctl.len = sizeof (dl_unitdata_req_t) + addrlen; ctl.buf = (char *) buf; data.maxlen = 0; data.len = datalen; data.buf = (char *) datap; if (putmsg(fd, &ctl, &data, 0) < 0) syserr("dlunitdatareq: putmsg"); } void dlunbindreq(int fd) { dl_unbind_req_t unbind_req; struct strbuf ctl; int flags; unbind_req.dl_primitive = DL_UNBIND_REQ; ctl.maxlen = 0; ctl.len = sizeof (unbind_req); ctl.buf = (char *) &unbind_req; flags = 0; if (putmsg(fd, &ctl, (struct strbuf*) NULL, flags) < 0) syserr("dlunbindreq: putmsg"); } void dlokack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlokack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_OK_ACK, dlp); if (ctl.len < sizeof (dl_ok_ack_t)) err("dlokack: response ctl.len too short: %d", ctl.len); if (flags != RS_HIPRI) err("dlokack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_ok_ack_t)) err("dlokack: short response ctl.len: %d", ctl.len); } void dlerrorack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlerrorack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_ERROR_ACK, dlp); if (ctl.len < sizeof (dl_error_ack_t)) err("dlerrorack: response ctl.len too short: %d", ctl.len); if (flags != RS_HIPRI) err("dlerrorack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_error_ack_t)) err("dlerrorack: short response ctl.len: %d", ctl.len); } void dlbindack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlbindack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_BIND_ACK, dlp); if (flags != RS_HIPRI) err("dlbindack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_bind_ack_t)) err("dlbindack: short response ctl.len: %d", ctl.len); } void dlphysaddrack(int fd, char *bufp) { union DL_primitives *dlp; struct strbuf ctl; int flags; ctl.maxlen = MAXDLBUF; ctl.len = 0; ctl.buf = bufp; strgetmsg(fd, &ctl, (struct strbuf*)NULL, &flags, "dlphysaddrack"); dlp = (union DL_primitives *) ctl.buf; expecting(DL_PHYS_ADDR_ACK, dlp); if (flags != RS_HIPRI) err("dlbindack: DL_OK_ACK was not M_PCPROTO"); if (ctl.len < sizeof (dl_phys_addr_ack_t)) err("dlphysaddrack: short response ctl.len: %d", ctl.len); } void sigalrm(void) { (void) err("sigalrm: TIMEOUT"); } strgetmsg(int fd, struct strbuf *ctlp, struct strbuf *datap, int *flagsp, char *caller) { int rc; static char errmsg[80]; /* * Start timer. */ (void) signal(SIGALRM, sigalrm); if (alarm(MAXWAIT) < 0) { (void) snprintf(errmsg, sizeof(errmsg), "%s: alarm", caller); syserr(errmsg); } /* * Set flags argument and issue getmsg(). */ *flagsp = 0; if ((rc = getmsg(fd, ctlp, datap, flagsp)) < 0) { (void) snprintf(errmsg, sizeof(errmsg), "%s: getmsg", caller); syserr(errmsg); } /* * Stop timer. */ if (alarm(0) < 0) { (void) snprintf(errmsg, sizeof(errmsg), "%s: alarm", caller); syserr(errmsg); } /* * Check for MOREDATA and/or MORECTL. */ if ((rc & (MORECTL | MOREDATA)) == (MORECTL | MOREDATA)) err("%s: MORECTL|MOREDATA", caller); if (rc & MORECTL) err("%s: MORECTL", caller); if (rc & MOREDATA) err("%s: MOREDATA", caller); /* * Check for at least sizeof (long) control data portion. */ if (ctlp->len < sizeof (long)) err("getmsg: control portion length < sizeof (long): %d", ctlp->len); } expecting(int prim, union DL_primitives *dlp) { if (dlp->dl_primitive != (u_long)prim) { printdlprim(dlp); err("expected %s got %s", dlprim(prim), dlprim(dlp->dl_primitive)); exit(1); } } /* * Print any DLPI msg in human readable format. */ printdlprim(union DL_primitives *dlp) { switch (dlp->dl_primitive) { case DL_INFO_REQ: printdlinforeq(dlp); break; case DL_INFO_ACK: printdlinfoack(dlp); break; case DL_ATTACH_REQ: printdlattachreq(dlp); break; case DL_OK_ACK: printdlokack(dlp); break; case DL_ERROR_ACK: printdlerrorack(dlp); break; case DL_DETACH_REQ: printdldetachreq(dlp); break; case DL_BIND_REQ: printdlbindreq(dlp); break; case DL_BIND_ACK: printdlbindack(dlp); break; case DL_UNBIND_REQ: printdlunbindreq(dlp); break; case DL_SUBS_BIND_REQ: printdlsubsbindreq(dlp); break; case DL_SUBS_BIND_ACK: printdlsubsbindack(dlp); break; case DL_SUBS_UNBIND_REQ: printdlsubsunbindreq(dlp); break; case DL_ENABMULTI_REQ: printdlenabmultireq(dlp); break; case DL_DISABMULTI_REQ: printdldisabmultireq(dlp); break; case DL_PROMISCON_REQ: printdlpromisconreq(dlp); break; case DL_PROMISCOFF_REQ: printdlpromiscoffreq(dlp); break; case DL_UNITDATA_REQ: printdlunitdatareq(dlp); break; case DL_UNITDATA_IND: printdlunitdataind(dlp); break; case DL_UDERROR_IND: printdluderrorind(dlp); break; case DL_UDQOS_REQ: printdludqosreq(dlp); break; case DL_PHYS_ADDR_REQ: printdlphysaddrreq(dlp); break; case DL_PHYS_ADDR_ACK: printdlphysaddrack(dlp); break; case DL_SET_PHYS_ADDR_REQ: printdlsetphysaddrreq(dlp); break; default: err("printdlprim: unknown primitive type 0x%x", dlp->dl_primitive); break; } } /* ARGSUSED */ printdlinforeq(union DL_primitives *dlp) { (void) printf("DL_INFO_REQ\n"); } printdlinfoack(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; u_char brdcst[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->info_ack.dl_addr_offset), dlp->info_ack.dl_addr_length, addr); addrtostring(OFFADDR(dlp, dlp->info_ack.dl_brdcst_addr_offset), dlp->info_ack.dl_brdcst_addr_length, brdcst); (void) printf("DL_INFO_ACK: max_sdu %d min_sdu %d\n", dlp->info_ack.dl_max_sdu, dlp->info_ack.dl_min_sdu); (void) printf("addr_length %d mac_type %s current_state %s\n", dlp->info_ack.dl_addr_length, dlmactype(dlp->info_ack.dl_mac_type), dlstate(dlp->info_ack.dl_current_state)); (void) printf("sap_length %d service_mode %s qos_length %d\n", dlp->info_ack.dl_sap_length, dlservicemode(dlp->info_ack.dl_service_mode), dlp->info_ack.dl_qos_length); (void) printf("qos_offset %d qos_range_length %d qos_range_offset %d\n", dlp->info_ack.dl_qos_offset, dlp->info_ack.dl_qos_range_length, dlp->info_ack.dl_qos_range_offset); (void) printf("provider_style %s addr_offset %d version %d\n", dlstyle(dlp->info_ack.dl_provider_style), dlp->info_ack.dl_addr_offset, dlp->info_ack.dl_version); (void) printf("brdcst_addr_length %d brdcst_addr_offset %d\n", dlp->info_ack.dl_brdcst_addr_length, dlp->info_ack.dl_brdcst_addr_offset); (void) printf("addr %s\n", addr); (void) printf("brdcst_addr %s\n", brdcst); } printdlattachreq(union DL_primitives *dlp) { (void) printf("DL_ATTACH_REQ: ppa %d\n", dlp->attach_req.dl_ppa); } printdlokack(union DL_primitives* dlp) union DL_primitives *dlp; { (void) printf("DL_OK_ACK: correct_primitive %s\n", dlprim(dlp->ok_ack.dl_correct_primitive)); } printdlerrorack(union DL_primitives *dlp) { (void) printf("DL_ERROR_ACK: error_primitive %s errno %s unix_errno %d: %s\n", dlprim(dlp->error_ack.dl_error_primitive), dlerrno(dlp->error_ack.dl_errno), dlp->error_ack.dl_unix_errno, strerror(dlp->error_ack.dl_unix_errno)); } printdlenabmultireq(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->enabmulti_req.dl_addr_offset), dlp->enabmulti_req.dl_addr_length, addr); (void) printf("DL_ENABMULTI_REQ: addr_length %d addr_offset %d\n", dlp->enabmulti_req.dl_addr_length, dlp->enabmulti_req.dl_addr_offset); (void) printf("addr %s\n", addr); } printdldisabmultireq(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->disabmulti_req.dl_addr_offset), dlp->disabmulti_req.dl_addr_length, addr); (void) printf("DL_DISABMULTI_REQ: addr_length %d addr_offset %d\n", dlp->disabmulti_req.dl_addr_length, dlp->disabmulti_req.dl_addr_offset); (void) printf("addr %s\n", addr); } printdlpromisconreq(union DL_primitives *dlp) { (void) printf("DL_PROMISCON_REQ: level %s\n", dlpromisclevel(dlp->promiscon_req.dl_level)); } printdlpromiscoffreq(union DL_primitives *dlp) { (void) printf("DL_PROMISCOFF_REQ: level %s\n", dlpromisclevel(dlp->promiscoff_req.dl_level)); } printdlphysaddrreq(union DL_primitives *dlp) { (void) printf("DL_PHYS_ADDR_REQ: addr_type 0x%x\n", dlp->physaddr_req.dl_addr_type); } printdlphysaddrack(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->physaddr_ack.dl_addr_offset), dlp->physaddr_ack.dl_addr_length, addr); (void) printf("DL_PHYS_ADDR_ACK: addr_length %d addr_offset %d\n", dlp->physaddr_ack.dl_addr_length, dlp->physaddr_ack.dl_addr_offset); (void) printf("addr %s\n", addr); } printdlsetphysaddrreq(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->set_physaddr_req.dl_addr_offset), dlp->set_physaddr_req.dl_addr_length, addr); (void) printf("DL_SET_PHYS_ADDR_REQ: addr_length %d addr_offset %d\n", dlp->set_physaddr_req.dl_addr_length, dlp->set_physaddr_req.dl_addr_offset); (void) printf("addr %s\n", addr); } /* ARGSUSED */ printdldetachreq(union DL_primitives *dlp) { (void) printf("DL_DETACH_REQ\n"); } printdlbindreq(union DL_primitives *dlp) { (void) printf("DL_BIND_REQ: sap %d max_conind %d\n", dlp->bind_req.dl_sap, dlp->bind_req.dl_max_conind); (void) printf("service_mode %s conn_mgmt %d xidtest_flg 0x%x\n", dlservicemode(dlp->bind_req.dl_service_mode), dlp->bind_req.dl_conn_mgmt, dlp->bind_req.dl_xidtest_flg); } printdlbindack(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->bind_ack.dl_addr_offset), dlp->bind_ack.dl_addr_length, addr); (void) printf("DL_BIND_ACK: sap %d addr_length %d addr_offset %d\n", dlp->bind_ack.dl_sap, dlp->bind_ack.dl_addr_length, dlp->bind_ack.dl_addr_offset); (void) printf("max_conind %d xidtest_flg 0x%x\n", dlp->bind_ack.dl_max_conind, dlp->bind_ack.dl_xidtest_flg); (void) printf("addr %s\n", addr); } /* ARGSUSED */ printdlunbindreq(union DL_primitives *dlp) { (void) printf("DL_UNBIND_REQ\n"); } printdlsubsbindreq(union DL_primitives *dlp) { u_char sap[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->subs_bind_req.dl_subs_sap_offset), dlp->subs_bind_req.dl_subs_sap_length, sap); (void) printf("DL_SUBS_BIND_REQ: subs_sap_offset %d sub_sap_len %d\n", dlp->subs_bind_req.dl_subs_sap_offset, dlp->subs_bind_req.dl_subs_sap_length); (void) printf("sap %s\n", sap); } printdlsubsbindack(union DL_primitives *dlp) { u_char sap[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->subs_bind_ack.dl_subs_sap_offset), dlp->subs_bind_ack.dl_subs_sap_length, sap); (void) printf("DL_SUBS_BIND_ACK: subs_sap_offset %d sub_sap_length %d\n", dlp->subs_bind_ack.dl_subs_sap_offset, dlp->subs_bind_ack.dl_subs_sap_length); (void) printf("sap %s\n", sap); } printdlsubsunbindreq(union DL_primitives *dlp) { u_char sap[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->subs_unbind_req.dl_subs_sap_offset), dlp->subs_unbind_req.dl_subs_sap_length, sap); (void) printf("DL_SUBS_UNBIND_REQ: subs_sap_offset %d sub_sap_length %d\n", dlp->subs_unbind_req.dl_subs_sap_offset, dlp->subs_unbind_req.dl_subs_sap_length); (void) printf("sap %s\n", sap); } printdlunitdatareq(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->unitdata_req.dl_dest_addr_offset), dlp->unitdata_req.dl_dest_addr_length, addr); (void) printf("DL_UNITDATA_REQ: dest_addr_length %d dest_addr_offset %d\n", dlp->unitdata_req.dl_dest_addr_length, dlp->unitdata_req.dl_dest_addr_offset); (void) printf("dl_priority.min %d dl_priority.max %d\n", dlp->unitdata_req.dl_priority.dl_min, dlp->unitdata_req.dl_priority.dl_max); (void) printf("addr %s\n", addr); } printdlunitdataind(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_dest_addr_offset), dlp->unitdata_ind.dl_dest_addr_length, dest); addrtostring(OFFADDR(dlp, dlp->unitdata_ind.dl_src_addr_offset), dlp->unitdata_ind.dl_src_addr_length, src); (void) printf("DL_UNITDATA_IND: dest_addr_length %d dest_addr_offset %d\n", dlp->unitdata_ind.dl_dest_addr_length, dlp->unitdata_ind.dl_dest_addr_offset); (void) printf("src_addr_length %d src_addr_offset %d\n", dlp->unitdata_ind.dl_src_addr_length, dlp->unitdata_ind.dl_src_addr_offset); (void) printf("group_address 0x%x\n", dlp->unitdata_ind.dl_group_address); (void) printf("dest %s\n", dest); (void) printf("src %s\n", src); } printdluderrorind(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->uderror_ind.dl_dest_addr_offset), dlp->uderror_ind.dl_dest_addr_length, addr); (void) printf("DL_UDERROR_IND: dest_addr_length %d dest_addr_offset %d\n", dlp->uderror_ind.dl_dest_addr_length, dlp->uderror_ind.dl_dest_addr_offset); (void) printf("unix_errno %d errno %s\n", dlp->uderror_ind.dl_unix_errno, dlerrno(dlp->uderror_ind.dl_errno)); (void) printf("addr %s\n", addr); } printdltestreq(union DL_primitives *dlp) { u_char addr[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->test_req.dl_dest_addr_offset), dlp->test_req.dl_dest_addr_length, addr); (void) printf("DL_TEST_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->test_req.dl_flag, dlp->test_req.dl_dest_addr_length, dlp->test_req.dl_dest_addr_offset); (void) printf("dest_addr %s\n", addr); } printdltestind(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->test_ind.dl_dest_addr_offset), dlp->test_ind.dl_dest_addr_length, dest); addrtostring(OFFADDR(dlp, dlp->test_ind.dl_src_addr_offset), dlp->test_ind.dl_src_addr_length, src); (void) printf("DL_TEST_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->test_ind.dl_flag, dlp->test_ind.dl_dest_addr_length, dlp->test_ind.dl_dest_addr_offset); (void) printf("src_addr_length %d src_addr_offset %d\n", dlp->test_ind.dl_src_addr_length, dlp->test_ind.dl_src_addr_offset); (void) printf("dest_addr %s\n", dest); (void) printf("src_addr %s\n", src); } printdltestres(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->test_res.dl_dest_addr_offset), dlp->test_res.dl_dest_addr_length, dest); (void) printf("DL_TEST_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->test_res.dl_flag, dlp->test_res.dl_dest_addr_length, dlp->test_res.dl_dest_addr_offset); (void) printf("dest_addr %s\n", dest); } printdltestcon(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->test_con.dl_dest_addr_offset), dlp->test_con.dl_dest_addr_length, dest); addrtostring(OFFADDR(dlp, dlp->test_con.dl_src_addr_offset), dlp->test_con.dl_src_addr_length, src); (void) printf("DL_TEST_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->test_con.dl_flag, dlp->test_con.dl_dest_addr_length, dlp->test_con.dl_dest_addr_offset); (void) printf("src_addr_length %d src_addr_offset %d\n", dlp->test_con.dl_src_addr_length, dlp->test_con.dl_src_addr_offset); (void) printf("dest_addr %s\n", dest); (void) printf("src_addr %s\n", src); } printdlxidreq(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->xid_req.dl_dest_addr_offset), dlp->xid_req.dl_dest_addr_length, dest); (void) printf("DL_XID_REQ: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->xid_req.dl_flag, dlp->xid_req.dl_dest_addr_length, dlp->xid_req.dl_dest_addr_offset); (void) printf("dest_addr %s\n", dest); } printdlxidind(dlpunion DL_primitives *) { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_dest_addr_offset), dlp->xid_ind.dl_dest_addr_length, dest); addrtostring(OFFADDR(dlp, dlp->xid_ind.dl_src_addr_offset), dlp->xid_ind.dl_src_addr_length, src); (void) printf("DL_XID_IND: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->xid_ind.dl_flag, dlp->xid_ind.dl_dest_addr_length, dlp->xid_ind.dl_dest_addr_offset); (void) printf("src_addr_length %d src_addr_offset %d\n", dlp->xid_ind.dl_src_addr_length, dlp->xid_ind.dl_src_addr_offset); (void) printf("dest_addr %s\n", dest); (void) printf("src_addr %s\n", src); } printdlxidres(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->xid_res.dl_dest_addr_offset), dlp->xid_res.dl_dest_addr_length, dest); (void) printf("DL_XID_RES: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->xid_res.dl_flag, dlp->xid_res.dl_dest_addr_length, dlp->xid_res.dl_dest_addr_offset); (void) printf("dest_addr %s\n", dest); } printdlxidcon(union DL_primitives *dlp) { u_char dest[MAXDLADDR]; u_char src[MAXDLADDR]; addrtostring(OFFADDR(dlp, dlp->xid_con.dl_dest_addr_offset), dlp->xid_con.dl_dest_addr_length, dest); addrtostring(OFFADDR(dlp, dlp->xid_con.dl_src_addr_offset), dlp->xid_con.dl_src_addr_length, src); (void) printf("DL_XID_CON: flag 0x%x dest_addr_length %d dest_addr_offset %d\n", dlp->xid_con.dl_flag, dlp->xid_con.dl_dest_addr_length, dlp->xid_con.dl_dest_addr_offset); (void) printf("src_addr_length %d src_addr_offset %d\n", dlp->xid_con.dl_src_addr_length, dlp->xid_con.dl_src_addr_offset); (void) printf("dest_addr %s\n", dest); (void) printf("src_addr %s\n", src); } printdludqosreq(union DL_primitives *dlp) { (void) printf("DL_UDQOS_REQ: qos_length %d qos_offset %d\n", dlp->udqos_req.dl_qos_length, dlp->udqos_req.dl_qos_offset); } /* * Return string. */ addrtostring(u_char *addr, u_long length, u_char *s) { int i; for (i = 0; i < length; i++) { (void) sprintf((char*) s, "%x:", addr[i] & 0xff); s = s + strlen((char*)s); } if (length) *(--s) = '\0'; } /* * Return length */ stringtoaddr(char *sp, char *addr) { int n = 0; char *p; int val; p = sp; while (p = strtok(p, ":")) { if (sscanf(p, "%x", &val) != 1) err("stringtoaddr: invalid input string: %s", sp); if (val > 0xff) err("stringtoaddr: invalid input string: %s", sp); *addr++ = val; n++; p = NULL; } - return (n); + return(n); } static char hexnibble(char c) { static char hextab[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - return (hextab[c & 0x0f]); + return(hextab[c & 0x0f]); } char* dlprim(u_long prim) { static char primbuf[80]; switch ((int)prim) { CASERET(DL_INFO_REQ); CASERET(DL_INFO_ACK); CASERET(DL_ATTACH_REQ); CASERET(DL_DETACH_REQ); CASERET(DL_BIND_REQ); CASERET(DL_BIND_ACK); CASERET(DL_UNBIND_REQ); CASERET(DL_OK_ACK); CASERET(DL_ERROR_ACK); CASERET(DL_SUBS_BIND_REQ); CASERET(DL_SUBS_BIND_ACK); CASERET(DL_UNITDATA_REQ); CASERET(DL_UNITDATA_IND); CASERET(DL_UDERROR_IND); CASERET(DL_UDQOS_REQ); CASERET(DL_CONNECT_REQ); CASERET(DL_CONNECT_IND); CASERET(DL_CONNECT_RES); CASERET(DL_CONNECT_CON); CASERET(DL_TOKEN_REQ); CASERET(DL_TOKEN_ACK); CASERET(DL_DISCONNECT_REQ); CASERET(DL_DISCONNECT_IND); CASERET(DL_RESET_REQ); CASERET(DL_RESET_IND); CASERET(DL_RESET_RES); CASERET(DL_RESET_CON); default: (void) snprintf(primbuf, sizeof(primbuf), "unknown primitive 0x%x", prim); - return (primbuf); + return(primbuf); } } char* dlstate(u_long state) { static char statebuf[80]; switch (state) { CASERET(DL_UNATTACHED); CASERET(DL_ATTACH_PENDING); CASERET(DL_DETACH_PENDING); CASERET(DL_UNBOUND); CASERET(DL_BIND_PENDING); CASERET(DL_UNBIND_PENDING); CASERET(DL_IDLE); CASERET(DL_UDQOS_PENDING); CASERET(DL_OUTCON_PENDING); CASERET(DL_INCON_PENDING); CASERET(DL_CONN_RES_PENDING); CASERET(DL_DATAXFER); CASERET(DL_USER_RESET_PENDING); CASERET(DL_PROV_RESET_PENDING); CASERET(DL_RESET_RES_PENDING); CASERET(DL_DISCON8_PENDING); CASERET(DL_DISCON9_PENDING); CASERET(DL_DISCON11_PENDING); CASERET(DL_DISCON12_PENDING); CASERET(DL_DISCON13_PENDING); CASERET(DL_SUBS_BIND_PND); default: (void) snprintf(statebuf, sizeof(statebuf), "unknown state 0x%x", state); - return (statebuf); + return(statebuf); } } char* dlerrno(u_long errno) { static char errnobuf[80]; switch (errno) { CASERET(DL_ACCESS); CASERET(DL_BADADDR); CASERET(DL_BADCORR); CASERET(DL_BADDATA); CASERET(DL_BADPPA); CASERET(DL_BADPRIM); CASERET(DL_BADQOSPARAM); CASERET(DL_BADQOSTYPE); CASERET(DL_BADSAP); CASERET(DL_BADTOKEN); CASERET(DL_BOUND); CASERET(DL_INITFAILED); CASERET(DL_NOADDR); CASERET(DL_NOTINIT); CASERET(DL_OUTSTATE); CASERET(DL_SYSERR); CASERET(DL_UNSUPPORTED); CASERET(DL_UNDELIVERABLE); CASERET(DL_NOTSUPPORTED); CASERET(DL_TOOMANY); CASERET(DL_NOTENAB); CASERET(DL_BUSY); CASERET(DL_NOAUTO); CASERET(DL_NOXIDAUTO); CASERET(DL_NOTESTAUTO); CASERET(DL_XIDAUTO); CASERET(DL_TESTAUTO); CASERET(DL_PENDING); default: (void) snprintf(errnobuf, sizeof(errnobuf), "unknown dlpi errno 0x%x", errno); - return (errnobuf); + return(errnobuf); } } char* dlpromisclevel(u_long level) { static char levelbuf[80]; switch (level) { CASERET(DL_PROMISC_PHYS); CASERET(DL_PROMISC_SAP); CASERET(DL_PROMISC_MULTI); default: (void) snprintf(levelbuf, sizeof(levelbuf), "unknown promisc level 0x%x", level); - return (levelbuf); + return(levelbuf); } } char* dlservicemode(u_long servicemode) { static char servicemodebuf[80]; switch (servicemode) { CASERET(DL_CODLS); CASERET(DL_CLDLS); CASERET(DL_CODLS|DL_CLDLS); default: (void) snprintf(servicemodebuf, sizeof(servicemodebuf), "unknown provider service mode 0x%x", servicemode); - return (servicemodebuf); + return(servicemodebuf); } } char* dlstyle(long style) { static char stylebuf[80]; switch (style) { CASERET(DL_STYLE1); CASERET(DL_STYLE2); default: (void) snprintf(stylebuf, sizeof(stylebuf), "unknown provider style 0x%x", style); - return (stylebuf); + return(stylebuf); } } char* dlmactype(u_long media) { static char mediabuf[80]; switch (media) { CASERET(DL_CSMACD); CASERET(DL_TPB); CASERET(DL_TPR); CASERET(DL_METRO); CASERET(DL_ETHER); CASERET(DL_HDLC); CASERET(DL_CHAR); CASERET(DL_CTCA); default: (void) snprintf(mediabuf, sizeof(mediabuf), "unknown media type 0x%x", media); - return (mediabuf); + return(mediabuf); } } /*VARARGS1*/ err(char *fmt, char *a1, char *a2, char *a3, char *a4) { (void) fprintf(stderr, fmt, a1, a2, a3, a4); (void) fprintf(stderr, "\n"); (void) exit(1); } syserr(char *s) char *s; { (void) perror(s); exit(1); } strioctl(int fd, int cmd, int timout, int len, char *dp) { struct strioctl sioc; int rc; sioc.ic_cmd = cmd; sioc.ic_timout = timout; sioc.ic_len = len; sioc.ic_dp = dp; rc = ioctl(fd, I_STR, &sioc); if (rc < 0) - return (rc); + return(rc); else - return (sioc.ic_len); + return(sioc.ic_len); } diff --git a/sbin/ipf/ipsend/ip.c b/sbin/ipf/ipsend/ip.c index 8a474704e3ab..7e24e459f8c3 100644 --- a/sbin/ipf/ipsend/ip.c +++ b/sbin/ipf/ipsend/ip.c @@ -1,351 +1,351 @@ /* $FreeBSD$ */ /* * ip.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include # include # include # include #include #include #include #include #include #include "ipsend.h" static char *ipbuf = NULL, *ethbuf = NULL; u_short chksum(u_short *buf, int len) { u_long sum = 0; int nwords = len >> 1; for(; nwords > 0; nwords--) sum += *buf++; sum = (sum>>16) + (sum & 0xffff); sum += (sum >>16); - return (~sum); + return(~sum); } int send_ether(int nfd, char *buf, int len, struct in_addr gwip) { static struct in_addr last_gw; static char last_arp[6] = { 0, 0, 0, 0, 0, 0}; ether_header_t *eh; char *s; int err; if (!ethbuf) ethbuf = (char *)calloc(1, 65536+1024); s = ethbuf; eh = (ether_header_t *)s; bcopy((char *)buf, s + sizeof(*eh), len); if (gwip.s_addr == last_gw.s_addr) { bcopy(last_arp, (char *) &eh->ether_dhost, 6); } else if (arp((char *)&gwip, (char *) &eh->ether_dhost) == -1) { perror("arp"); - return -2; + return(-2); } eh->ether_type = htons(ETHERTYPE_IP); last_gw.s_addr = gwip.s_addr; err = sendip(nfd, s, sizeof(*eh) + len); - return err; + return(err); } /* */ int send_ip(int nfd, int mtu, ip_t *ip, struct in_addr gwip, int frag) { static struct in_addr last_gw, local_ip; static char local_arp[6] = { 0, 0, 0, 0, 0, 0}; static char last_arp[6] = { 0, 0, 0, 0, 0, 0}; static u_short id = 0; ether_header_t *eh; ip_t ipsv; int err, iplen; if (!ipbuf) { ipbuf = (char *)malloc(65536); if (!ipbuf) { perror("malloc failed"); - return -2; + return(-2); } } eh = (ether_header_t *)ipbuf; bzero((char *) &eh->ether_shost, sizeof(eh->ether_shost)); if (last_gw.s_addr && (gwip.s_addr == last_gw.s_addr)) { bcopy(last_arp, (char *) &eh->ether_dhost, 6); } else if (arp((char *)&gwip, (char *) &eh->ether_dhost) == -1) { perror("arp"); - return -2; + return(-2); } bcopy((char *) &eh->ether_dhost, last_arp, sizeof(last_arp)); eh->ether_type = htons(ETHERTYPE_IP); bcopy((char *)ip, (char *)&ipsv, sizeof(*ip)); last_gw.s_addr = gwip.s_addr; iplen = ip->ip_len; ip->ip_len = htons(iplen); if (!(frag & 2)) { if (!IP_V(ip)) IP_V_A(ip, IPVERSION); if (!ip->ip_id) ip->ip_id = htons(id++); if (!ip->ip_ttl) ip->ip_ttl = 60; } if (ip->ip_src.s_addr != local_ip.s_addr) { (void) arp((char *)&ip->ip_src, (char *) &local_arp); bcopy(local_arp, (char *) &eh->ether_shost,sizeof(last_arp)); local_ip = ip->ip_src; } else bcopy(local_arp, (char *) &eh->ether_shost, 6); if (!frag || (sizeof(*eh) + iplen < mtu)) { ip->ip_sum = 0; ip->ip_sum = chksum((u_short *)ip, IP_HL(ip) << 2); bcopy((char *)ip, ipbuf + sizeof(*eh), iplen); err = sendip(nfd, ipbuf, sizeof(*eh) + iplen); } else { /* * Actually, this is bogus because we're putting all IP * options in every packet, which isn't always what should be * done. Will do for now. */ ether_header_t eth; char optcpy[48], ol; char *s; int i, sent = 0, ts, hlen, olen; hlen = IP_HL(ip) << 2; if (mtu < (hlen + 8)) { fprintf(stderr, "mtu (%d) < ip header size (%d) + 8\n", mtu, hlen); fprintf(stderr, "can't fragment data\n"); - return -2; + return(-2); } ol = (IP_HL(ip) << 2) - sizeof(*ip); for (i = 0, s = (char*)(ip + 1); ol > 0; ) if (*s == IPOPT_EOL) { optcpy[i++] = *s; break; } else if (*s == IPOPT_NOP) { s++; ol--; } else { olen = (int)(*(u_char *)(s + 1)); ol -= olen; if (IPOPT_COPIED(*s)) { bcopy(s, optcpy + i, olen); i += olen; s += olen; } } if (i) { /* * pad out */ while ((i & 3) && (i & 3) != 3) optcpy[i++] = IPOPT_NOP; if ((i & 3) == 3) optcpy[i++] = IPOPT_EOL; } bcopy((char *)eh, (char *)ð, sizeof(eth)); s = (char *)ip + hlen; iplen = ntohs(ip->ip_len) - hlen; ip->ip_off |= htons(IP_MF); while (1) { if ((sent + (mtu - hlen)) >= iplen) { ip->ip_off ^= htons(IP_MF); ts = iplen - sent; } else ts = (mtu - hlen); ip->ip_off &= htons(0xe000); ip->ip_off |= htons(sent >> 3); ts += hlen; ip->ip_len = htons(ts); ip->ip_sum = 0; ip->ip_sum = chksum((u_short *)ip, hlen); bcopy((char *)ip, ipbuf + sizeof(*eh), hlen); bcopy(s + sent, ipbuf + sizeof(*eh) + hlen, ts - hlen); err = sendip(nfd, ipbuf, sizeof(*eh) + ts); bcopy((char *)ð, ipbuf, sizeof(eth)); sent += (ts - hlen); if (!(ntohs(ip->ip_off) & IP_MF)) break; else if (!(ip->ip_off & htons(0x1fff))) { hlen = i + sizeof(*ip); IP_HL_A(ip, (sizeof(*ip) + i) >> 2); bcopy(optcpy, (char *)(ip + 1), i); } } } bcopy((char *)&ipsv, (char *)ip, sizeof(*ip)); - return err; + return(err); } /* * send a tcp packet. */ int send_tcp(int nfd, int mtu, ip_t *ip, struct in_addr gwip) { static tcp_seq iss = 2; tcphdr_t *t, *t2; int thlen, i, iplen, hlen; u_32_t lbuf[20]; ip_t *ip2; iplen = ip->ip_len; hlen = IP_HL(ip) << 2; t = (tcphdr_t *)((char *)ip + hlen); ip2 = (struct ip *)lbuf; t2 = (tcphdr_t *)((char *)ip2 + hlen); thlen = TCP_OFF(t) << 2; if (!thlen) thlen = sizeof(tcphdr_t); bzero((char *)ip2, sizeof(*ip2) + sizeof(*t2)); ip->ip_p = IPPROTO_TCP; ip2->ip_p = ip->ip_p; ip2->ip_src = ip->ip_src; ip2->ip_dst = ip->ip_dst; bcopy((char *)ip + hlen, (char *)t2, thlen); if (!t2->th_win) t2->th_win = htons(4096); iss += 63; i = sizeof(struct tcpiphdr) / sizeof(long); if ((t2->th_flags == TH_SYN) && !ntohs(ip->ip_off) && (lbuf[i] != htonl(0x020405b4))) { lbuf[i] = htonl(0x020405b4); bcopy((char *)ip + hlen + thlen, (char *)ip + hlen + thlen + 4, iplen - thlen - hlen); thlen += 4; } TCP_OFF_A(t2, thlen >> 2); ip2->ip_len = htons(thlen); ip->ip_len = hlen + thlen; t2->th_sum = 0; t2->th_sum = chksum((u_short *)ip2, thlen + sizeof(ip_t)); bcopy((char *)t2, (char *)ip + hlen, thlen); - return send_ip(nfd, mtu, ip, gwip, 1); + return(send_ip(nfd, mtu, ip, gwip, 1)); } /* * send a udp packet. */ int send_udp(int nfd, int mtu, ip_t *ip, struct in_addr gwip) { struct tcpiphdr *ti; int thlen; u_long lbuf[20]; ti = (struct tcpiphdr *)lbuf; bzero((char *)ti, sizeof(*ti)); thlen = sizeof(udphdr_t); ti->ti_pr = ip->ip_p; ti->ti_src = ip->ip_src; ti->ti_dst = ip->ip_dst; bcopy((char *)ip + (IP_HL(ip) << 2), (char *)&ti->ti_sport, sizeof(udphdr_t)); ti->ti_len = htons(thlen); ip->ip_len = (IP_HL(ip) << 2) + thlen; ti->ti_sum = 0; ti->ti_sum = chksum((u_short *)ti, thlen + sizeof(ip_t)); bcopy((char *)&ti->ti_sport, (char *)ip + (IP_HL(ip) << 2), sizeof(udphdr_t)); - return send_ip(nfd, mtu, ip, gwip, 1); + return(send_ip(nfd, mtu, ip, gwip, 1)); } /* * send an icmp packet. */ int send_icmp(int nfd, int mtu, ip_t *ip, in_addr gwip) { struct icmp *ic; ic = (struct icmp *)((char *)ip + (IP_HL(ip) << 2)); ic->icmp_cksum = 0; ic->icmp_cksum = chksum((u_short *)ic, sizeof(struct icmp)); - return send_ip(nfd, mtu, ip, gwip, 1); + return(send_ip(nfd, mtu, ip, gwip, 1)); } int send_packet(int nfd, int mtu, ip_t *ip, struct in_addr gwip) int nfd, mtu; ip_t *ip; struct in_addr gwip; { switch (ip->ip_p) { case IPPROTO_TCP : - return send_tcp(nfd, mtu, ip, gwip); +( return send_tcp(nfd, mtu, ip, gwip)); case IPPROTO_UDP : - return send_udp(nfd, mtu, ip, gwip); +( return send_udp(nfd, mtu, ip, gwip)); case IPPROTO_ICMP : - return send_icmp(nfd, mtu, ip, gwip); +( return send_icmp(nfd, mtu, ip, gwip)); default : - return send_ip(nfd, mtu, ip, gwip, 1); +( return send_ip(nfd, mtu, ip, gwip, 1)); } } diff --git a/sbin/ipf/ipsend/ipresend.c b/sbin/ipf/ipsend/ipresend.c index 2efb2eb4eeed..572c614f637e 100644 --- a/sbin/ipf/ipsend/ipresend.c +++ b/sbin/ipf/ipsend/ipresend.c @@ -1,132 +1,132 @@ /* $FreeBSD$ */ /* * ipresend.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" extern char *optarg; extern int optind; #ifndef NO_IPF extern struct ipread pcap, iphex, iptext; #endif int opts = 0; #ifndef DEFAULT_DEVICE # ifdef sun char default_device[] = "le0"; # else char default_device[] = "lan0"; # endif #else char default_device[] = DEFAULT_DEVICE; #endif static void usage(char *); int main(int, char **); static void usage(prog) char *prog; { fprintf(stderr, "Usage: %s [options] <-r filename|-R filename>\n\ \t\t-r filename\tsnoop data file to resend\n\ \t\t-R filename\tlibpcap data file to resend\n\ \toptions:\n\ \t\t-d device\tSend out on this device\n\ \t\t-g gateway\tIP gateway to use if non-local dest.\n\ \t\t-m mtu\t\tfake MTU to use when sending out\n\ ", prog); exit(1); } int main(int argc, char **argv) { struct in_addr gwip; struct ipread *ipr = NULL; char *name = argv[0], *gateway = NULL, *dev = NULL; char *resend = NULL; int mtu = 1500, c; while ((c = getopt(argc, argv, "EHPRSTXd:g:m:r:")) != -1) switch (c) { case 'd' : dev = optarg; break; case 'g' : gateway = optarg; break; case 'm' : mtu = atoi(optarg); if (mtu < 28) { fprintf(stderr, "mtu must be > 28\n"); exit(1); } case 'r' : resend = optarg; break; case 'R' : opts |= OPT_RAW; break; #ifndef NO_IPF case 'H' : ipr = &iphex; break; case 'P' : ipr = &pcap; break; case 'X' : ipr = &iptext; break; #endif default : fprintf(stderr, "Unknown option \"%c\"\n", c); usage(name); } if (!ipr || !resend) usage(name); gwip.s_addr = 0; if (gateway && resolve(gateway, (char *)&gwip) == -1) { fprintf(stderr,"Cant resolve %s\n", gateway); exit(2); } if (!dev) dev = default_device; printf("Device: %s\n", dev); printf("Gateway: %s\n", inet_ntoa(gwip)); printf("mtu: %d\n", mtu); - return ip_resend(dev, mtu, ipr, gwip, resend); + return(ip_resend(dev, mtu, ipr, gwip, resend)); } diff --git a/sbin/ipf/ipsend/ipsend.c b/sbin/ipf/ipsend/ipsend.c index b8111806397f..04dd4f3da71c 100644 --- a/sbin/ipf/ipsend/ipsend.c +++ b/sbin/ipf/ipsend/ipsend.c @@ -1,411 +1,411 @@ /* $FreeBSD$ */ /* * ipsend.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include # include #include "ipsend.h" #include "ipf.h" # include extern char *optarg; extern int optind; extern void iplang(FILE *); char options[68]; int opts; char default_device[] = "le0"; static void usage(char *); static void do_icmp(ip_t *, char *); void udpcksum(ip_t *, struct udphdr *, int); int main(int, char **); static void usage(prog) char *prog; { fprintf(stderr, "Usage: %s [options] dest [flags]\n\ \toptions:\n\ \t\t-d\tdebug mode\n\ \t\t-i device\tSend out on this device\n\ \t\t-f fragflags\tcan set IP_MF or IP_DF\n\ \t\t-g gateway\tIP gateway to use if non-local dest.\n\ \t\t-I code,type[,gw[,dst[,src]]]\tSet ICMP protocol\n\ \t\t-m mtu\t\tfake MTU to use when sending out\n\ \t\t-P protocol\tSet protocol by name\n\ \t\t-s src\t\tsource address for IP packet\n\ \t\t-T\t\tSet TCP protocol\n\ \t\t-t port\t\tdestination port\n\ \t\t-U\t\tSet UDP protocol\n\ \t\t-v\tverbose mode\n\ \t\t-w \tSet the TCP window size\n\ ", prog); fprintf(stderr, "Usage: %s [-dv] -L \n\ \toptions:\n\ \t\t-d\tdebug mode\n\ \t\t-L filename\tUse IP language for sending packets\n\ \t\t-v\tverbose mode\n\ ", prog); exit(1); } static void do_icmp(ip_t *ip, char *args) { struct icmp *ic; char *s; ip->ip_p = IPPROTO_ICMP; ip->ip_len += sizeof(*ic); ic = (struct icmp *)(ip + 1); bzero((char *)ic, sizeof(*ic)); if (!(s = strchr(args, ','))) { fprintf(stderr, "ICMP args missing: ,\n"); return; } *s++ = '\0'; ic->icmp_type = atoi(args); ic->icmp_code = atoi(s); if (ic->icmp_type == ICMP_REDIRECT && strchr(s, ',')) { char *t; t = strtok(s, ","); t = strtok(NULL, ","); if (resolve(t, (char *)&ic->icmp_gwaddr) == -1) { fprintf(stderr,"Cant resolve %s\n", t); exit(2); } if ((t = strtok(NULL, ","))) { if (resolve(t, (char *)&ic->icmp_ip.ip_dst) == -1) { fprintf(stderr,"Cant resolve %s\n", t); exit(2); } if ((t = strtok(NULL, ","))) { if (resolve(t, (char *)&ic->icmp_ip.ip_src) == -1) { fprintf(stderr,"Cant resolve %s\n", t); exit(2); } } } } } int send_packets(char *dev, int mtu, ip_t *ip, struct in_addr gwip) { int wfd; wfd = initdevice(dev, 5); if (wfd == -1) - return -1; - return send_packet(wfd, mtu, ip, gwip); + return(-1); + return(send_packet(wfd, mtu, ip, gwip)); } void udpcksum(ip_t *ip, struct udphdr *udp, int len) { union pseudoh { struct hdr { u_short len; u_char ttl; u_char proto; u_32_t src; u_32_t dst; } h; u_short w[6]; } ph; u_32_t temp32; u_short *opts; ph.h.len = htons(len); ph.h.ttl = 0; ph.h.proto = IPPROTO_UDP; ph.h.src = ip->ip_src.s_addr; ph.h.dst = ip->ip_dst.s_addr; temp32 = 0; opts = &ph.w[0]; temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5]; temp32 = (temp32 >> 16) + (temp32 & 65535); temp32 += (temp32 >> 16); udp->uh_sum = temp32 & 65535; udp->uh_sum = chksum((u_short *)udp, len); if (udp->uh_sum == 0) udp->uh_sum = 0xffff; } int main(int argc, char **argv) { FILE *langfile = NULL; struct in_addr gwip; tcphdr_t *tcp; udphdr_t *udp; ip_t *ip; char *name = argv[0], host[MAXHOSTNAMELEN + 1]; char *gateway = NULL, *dev = NULL; char *src = NULL, *dst, *s; int mtu = 1500, olen = 0, c, nonl = 0; /* * 65535 is maximum packet size...you never know... */ ip = (ip_t *)calloc(1, 65536); tcp = (tcphdr_t *)(ip + 1); udp = (udphdr_t *)tcp; ip->ip_len = sizeof(*ip); IP_HL_A(ip, sizeof(*ip) >> 2); while ((c = getopt(argc, argv, "I:L:P:TUdf:i:g:m:o:s:t:vw:")) != -1) { switch (c) { case 'I' : nonl++; if (ip->ip_p) { fprintf(stderr, "Protocol already set: %d\n", ip->ip_p); break; } do_icmp(ip, optarg); break; case 'L' : if (nonl) { fprintf(stderr, "Incorrect usage of -L option.\n"); usage(name); } if (!strcmp(optarg, "-")) langfile = stdin; else if (!(langfile = fopen(optarg, "r"))) { fprintf(stderr, "can't open file %s\n", optarg); exit(1); } iplang(langfile); - return 0; + return(0); case 'P' : { struct protoent *p; nonl++; if (ip->ip_p) { fprintf(stderr, "Protocol already set: %d\n", ip->ip_p); break; } if ((p = getprotobyname(optarg))) ip->ip_p = p->p_proto; else fprintf(stderr, "Unknown protocol: %s\n", optarg); break; } case 'T' : nonl++; if (ip->ip_p) { fprintf(stderr, "Protocol already set: %d\n", ip->ip_p); break; } ip->ip_p = IPPROTO_TCP; ip->ip_len += sizeof(tcphdr_t); break; case 'U' : nonl++; if (ip->ip_p) { fprintf(stderr, "Protocol already set: %d\n", ip->ip_p); break; } ip->ip_p = IPPROTO_UDP; ip->ip_len += sizeof(udphdr_t); break; case 'd' : opts |= OPT_DEBUG; break; case 'f' : nonl++; ip->ip_off = strtol(optarg, NULL, 0); break; case 'g' : nonl++; gateway = optarg; break; case 'i' : nonl++; dev = optarg; break; case 'm' : nonl++; mtu = atoi(optarg); if (mtu < 28) { fprintf(stderr, "mtu must be > 28\n"); exit(1); } break; case 'o' : nonl++; olen = buildopts(optarg, options, (IP_HL(ip) - 5) << 2); break; case 's' : nonl++; src = optarg; break; case 't' : nonl++; if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) tcp->th_dport = htons(atoi(optarg)); break; case 'v' : opts |= OPT_VERBOSE; break; case 'w' : nonl++; if (ip->ip_p == IPPROTO_TCP) tcp->th_win = atoi(optarg); else fprintf(stderr, "set protocol to TCP first\n"); break; default : fprintf(stderr, "Unknown option \"%c\"\n", c); usage(name); } } if (argc - optind < 1) usage(name); dst = argv[optind++]; if (!src) { gethostname(host, sizeof(host)); src = host; } if (resolve(src, (char *)&ip->ip_src) == -1) { fprintf(stderr,"Cant resolve %s\n", src); exit(2); } if (resolve(dst, (char *)&ip->ip_dst) == -1) { fprintf(stderr,"Cant resolve %s\n", dst); exit(2); } if (!gateway) gwip = ip->ip_dst; else if (resolve(gateway, (char *)&gwip) == -1) { fprintf(stderr,"Cant resolve %s\n", gateway); exit(2); } if (olen) { int hlen; char *p; printf("Options: %d\n", olen); hlen = sizeof(*ip) + olen; IP_HL_A(ip, hlen >> 2); ip->ip_len += olen; p = (char *)malloc(65536); if (p == NULL) { fprintf(stderr, "malloc failed\n"); exit(2); } bcopy(ip, p, sizeof(*ip)); bcopy(options, p + sizeof(*ip), olen); bcopy(ip + 1, p + hlen, ip->ip_len - hlen); ip = (ip_t *)p; if (ip->ip_p == IPPROTO_TCP) { tcp = (tcphdr_t *)(p + hlen); } else if (ip->ip_p == IPPROTO_UDP) { udp = (udphdr_t *)(p + hlen); } } if (ip->ip_p == IPPROTO_TCP) for (s = argv[optind]; s && (c = *s); s++) switch(c) { case 'S' : case 's' : tcp->th_flags |= TH_SYN; break; case 'A' : case 'a' : tcp->th_flags |= TH_ACK; break; case 'F' : case 'f' : tcp->th_flags |= TH_FIN; break; case 'R' : case 'r' : tcp->th_flags |= TH_RST; break; case 'P' : case 'p' : tcp->th_flags |= TH_PUSH; break; case 'U' : case 'u' : tcp->th_flags |= TH_URG; break; } if (!dev) dev = default_device; printf("Device: %s\n", dev); printf("Source: %s\n", inet_ntoa(ip->ip_src)); printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); printf("Gateway: %s\n", inet_ntoa(gwip)); if (ip->ip_p == IPPROTO_TCP && tcp->th_flags) printf("Flags: %#x\n", tcp->th_flags); printf("mtu: %d\n", mtu); if (ip->ip_p == IPPROTO_UDP) { udp->uh_sum = 0; udpcksum(ip, udp, ip->ip_len - (IP_HL(ip) << 2)); } #ifdef DOSOCKET if (ip->ip_p == IPPROTO_TCP && tcp->th_dport) - return do_socket(dev, mtu, ip, gwip); + return(do_socket(dev, mtu, ip, gwip)); #endif - return send_packets(dev, mtu, ip, gwip); + return(send_packets(dev, mtu, ip, gwip)); } diff --git a/sbin/ipf/ipsend/ipsopt.c b/sbin/ipf/ipsend/ipsopt.c index e5585d906d7f..f48dffb8bc48 100644 --- a/sbin/ipf/ipsend/ipsopt.c +++ b/sbin/ipf/ipsend/ipsopt.c @@ -1,192 +1,192 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" #ifndef __P # define __P(x) x #endif struct ipopt_names ionames[] = { { IPOPT_EOL, 0x01, 1, "eol" }, { IPOPT_NOP, 0x02, 1, "nop" }, { IPOPT_RR, 0x04, 3, "rr" }, /* 1 route */ { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */ { IPOPT_SECURITY, 0x08, 11, "sec-level" }, { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ { IPOPT_SATID, 0x20, 4, "satid" }, { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ { 0, 0, 0, NULL } /* must be last */ }; struct ipopt_names secnames[] = { { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" }, { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" }, { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" }, { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" }, { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" }, { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" }, { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" }, { 0, 0, 0, NULL } /* must be last */ }; u_short ipseclevel(slevel) char *slevel; { struct ipopt_names *so; for (so = secnames; so->on_name; so++) if (!strcasecmp(slevel, so->on_name)) break; if (!so->on_name) { fprintf(stderr, "no such security level: %s\n", slevel); - return 0; + return(0); } - return so->on_value; + return(so->on_value); } int addipopt(char *op, struct ipopt_names *io, int len, char *class) { struct in_addr ipadr; int olen = len, srr = 0; u_short val; u_char lvl; char *s = op, *t; if ((len + io->on_siz) > 48) { fprintf(stderr, "options too long\n"); - return 0; + return(0); } len += io->on_siz; *op++ = io->on_value; if (io->on_siz > 1) { /* * Allow option to specify RR buffer length in bytes. */ if (io->on_value == IPOPT_RR) { val = (class && *class) ? atoi(class) : 4; *op++ = val + io->on_siz; len += val; } else *op++ = io->on_siz; if (io->on_value == IPOPT_TS) *op++ = IPOPT_MINOFF + 1; else *op++ = IPOPT_MINOFF; while (class && *class) { t = NULL; switch (io->on_value) { case IPOPT_SECURITY : lvl = ipseclevel(class); *(op - 1) = lvl; break; case IPOPT_LSRR : case IPOPT_SSRR : if ((t = strchr(class, ','))) *t = '\0'; ipadr.s_addr = inet_addr(class); srr++; bcopy((char *)&ipadr, op, sizeof(ipadr)); op += sizeof(ipadr); break; case IPOPT_SATID : val = atoi(class); bcopy((char *)&val, op, 2); break; } if (t) *t++ = ','; class = t; } if (srr) s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4 * srr; if (io->on_value == IPOPT_RR) op += val; else op += io->on_siz - 3; } - return len - olen; + return(len - olen); } u_32_t buildopts(char *cp, char *op, int len) char *cp, *op; int len; { struct ipopt_names *io; u_32_t msk = 0; char *s, *t; int inc, lastop = -1; for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { if ((t = strchr(s, '='))) *t++ = '\0'; for (io = ionames; io->on_name; io++) { if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) continue; lastop = io->on_value; if ((inc = addipopt(op, io, len, t))) { op += inc; len += inc; } msk |= io->on_bit; break; } if (!io->on_name) { fprintf(stderr, "unknown IP option name %s\n", s); - return 0; + return(0); } } if (len & 3) { while (len & 3) { *op++ = ((len & 3) == 3) ? IPOPT_EOL : IPOPT_NOP; len++; } } else { if (lastop != IPOPT_EOL) { if (lastop == IPOPT_NOP) *(op - 1) = IPOPT_EOL; else { *op++ = IPOPT_NOP; *op++ = IPOPT_NOP; *op++ = IPOPT_NOP; *op = IPOPT_EOL; len += 4; } } } - return len; + return(len); } diff --git a/sbin/ipf/ipsend/iptest.c b/sbin/ipf/ipsend/iptest.c index e6c57c3cdbbd..53c960b8c97b 100644 --- a/sbin/ipf/ipsend/iptest.c +++ b/sbin/ipf/ipsend/iptest.c @@ -1,196 +1,196 @@ /* $FreeBSD$ */ /* * ipsend.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "%W% %G% (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" extern char *optarg; extern int optind; char options[68]; # ifdef sun char default_device[] = "le0"; # else char default_device[] = "lan0"; # endif static void usage(char *); int main(int, char **); static void usage(prog) char *prog; { fprintf(stderr, "Usage: %s [options] dest\n\ \toptions:\n\ \t\t-d device\tSend out on this device\n\ \t\t-g gateway\tIP gateway to use if non-local dest.\n\ \t\t-m mtu\t\tfake MTU to use when sending out\n\ \t\t-p pointtest\t\n\ \t\t-s src\t\tsource address for IP packet\n\ \t\t-1 \t\tPerform test 1 (IP header)\n\ \t\t-2 \t\tPerform test 2 (IP options)\n\ \t\t-3 \t\tPerform test 3 (ICMP)\n\ \t\t-4 \t\tPerform test 4 (UDP)\n\ \t\t-5 \t\tPerform test 5 (TCP)\n\ \t\t-6 \t\tPerform test 6 (overlapping fragments)\n\ \t\t-7 \t\tPerform test 7 (random packets)\n\ ", prog); exit(1); } int main(int argc, char **argv) { struct tcpiphdr *ti; struct in_addr gwip; ip_t *ip; char *name = argv[0], host[MAXHOSTNAMELEN + 1]; char *gateway = NULL, *dev = NULL; char *src = NULL, *dst; int mtu = 1500, tests = 0, pointtest = 0, c; /* * 65535 is maximum packet size...you never know... */ ip = (ip_t *)calloc(1, 65536); ti = (struct tcpiphdr *)ip; ip->ip_len = sizeof(*ip); IP_HL_A(ip, sizeof(*ip) >> 2); while ((c = getopt(argc, argv, "1234567d:g:m:p:s:")) != -1) switch (c) { case '1' : case '2' : case '3' : case '4' : case '5' : case '6' : case '7' : tests = c - '0'; break; case 'd' : dev = optarg; break; case 'g' : gateway = optarg; break; case 'm' : mtu = atoi(optarg); if (mtu < 28) { fprintf(stderr, "mtu must be > 28\n"); exit(1); } break; case 'p' : pointtest = atoi(optarg); break; case 's' : src = optarg; break; default : fprintf(stderr, "Unknown option \"%c\"\n", c); usage(name); } if ((argc <= optind) || !argv[optind]) usage(name); dst = argv[optind++]; if (!src) { gethostname(host, sizeof(host)); host[sizeof(host) - 1] = '\0'; src = host; } if (resolve(dst, (char *)&ip->ip_dst) == -1) { fprintf(stderr,"Cant resolve %s\n", dst); exit(2); } if (resolve(src, (char *)&ip->ip_src) == -1) { fprintf(stderr,"Cant resolve %s\n", src); exit(2); } if (!gateway) gwip = ip->ip_dst; else if (resolve(gateway, (char *)&gwip) == -1) { fprintf(stderr,"Cant resolve %s\n", gateway); exit(2); } if (!dev) dev = default_device; printf("Device: %s\n", dev); printf("Source: %s\n", inet_ntoa(ip->ip_src)); printf("Dest: %s\n", inet_ntoa(ip->ip_dst)); printf("Gateway: %s\n", inet_ntoa(gwip)); printf("mtu: %d\n", mtu); switch (tests) { case 1 : ip_test1(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 2 : ip_test2(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 3 : ip_test3(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 4 : ip_test4(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 5 : ip_test5(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 6 : ip_test6(dev, mtu, (ip_t *)ti, gwip, pointtest); break; case 7 : ip_test7(dev, mtu, (ip_t *)ti, gwip, pointtest); break; default : ip_test1(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test2(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test3(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test4(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test5(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test6(dev, mtu, (ip_t *)ti, gwip, pointtest); ip_test7(dev, mtu, (ip_t *)ti, gwip, pointtest); break; } - return 0; + return(0); } diff --git a/sbin/ipf/ipsend/resend.c b/sbin/ipf/ipsend/resend.c index 537eb0a262b7..e797150dee0b 100644 --- a/sbin/ipf/ipsend/resend.c +++ b/sbin/ipf/ipsend/resend.c @@ -1,138 +1,138 @@ /* $FreeBSD$ */ /* * resend.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #include #include #include #include #include # include # include #include #include #include #include #include #include "ipsend.h" extern int opts; void dumppacket(ip_t *); void dumppacket(ip_t *ip) { tcphdr_t *t; int i, j; t = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); if (ip->ip_tos) printf("tos %#x ", ip->ip_tos); if (ip->ip_off & 0x3fff) printf("frag @%#x ", (ip->ip_off & 0x1fff) << 3); printf("len %d id %d ", ip->ip_len, ip->ip_id); printf("ttl %d p %d src %s", ip->ip_ttl, ip->ip_p, inet_ntoa(ip->ip_src)); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) printf(",%d", t->th_sport); printf(" dst %s", inet_ntoa(ip->ip_dst)); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) printf(",%d", t->th_dport); if (ip->ip_p == IPPROTO_TCP) { printf(" seq %lu:%lu flags ", (u_long)t->th_seq, (u_long)t->th_ack); for (j = 0, i = 1; i < 256; i *= 2, j++) if (t->th_flags & i) printf("%c", "FSRPAU--"[j]); } putchar('\n'); } int ip_resend(char *dev, int mtu, struct ipread *r, struct in_addr gwip, char *datain) { ether_header_t *eh; char dhost[6]; ip_t *ip; int fd, wfd = initdevice(dev, 5), len, i; mb_t mb; if (wfd == -1) - return -1; + return(-1); if (datain) fd = (*r->r_open)(datain); else fd = (*r->r_open)("-"); if (fd < 0) exit(-1); ip = (struct ip *)mb.mb_buf; eh = (ether_header_t *)malloc(sizeof(*eh)); if(!eh) { perror("malloc failed"); - return -2; + return(-2); } bzero((char *) &eh->ether_shost, sizeof(eh->ether_shost)); if (gwip.s_addr && (arp((char *)&gwip, dhost) == -1)) { perror("arp"); free(eh); - return -2; + return(-2); } while ((i = (*r->r_readip)(&mb, NULL, NULL)) > 0) { if (!(opts & OPT_RAW)) { len = ntohs(ip->ip_len); eh = (ether_header_t *)realloc((char *)eh, sizeof(*eh) + len); eh->ether_type = htons((u_short)ETHERTYPE_IP); if (!gwip.s_addr) { if (arp((char *)&gwip, (char *) &eh->ether_dhost) == -1) { perror("arp"); continue; } } else bcopy(dhost, (char *) &eh->ether_dhost, sizeof(dhost)); if (!ip->ip_sum) ip->ip_sum = chksum((u_short *)ip, IP_HL(ip) << 2); bcopy(ip, (char *)(eh + 1), len); len += sizeof(*eh); dumppacket(ip); } else { eh = (ether_header_t *)mb.mb_buf; len = i; } if (sendip(wfd, (char *)eh, len) == -1) { perror("send_packet"); break; } } (*r->r_close)(); free(eh); - return 0; + return(0); } diff --git a/sbin/ipf/ipsend/sbpf.c b/sbin/ipf/ipsend/sbpf.c index c1b8cc546961..5df7cf14cb74 100644 --- a/sbin/ipf/ipsend/sbpf.c +++ b/sbin/ipf/ipsend/sbpf.c @@ -1,148 +1,148 @@ /* $FreeBSD$ */ /* * (C)opyright 1995-1998 Darren Reed. (from tcplog) * * See the IPFILTER.LICENCE file for details on licencing. * */ #include #include #include #include #include #include #include #ifdef __FreeBSD__ # include #else # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __NetBSD__ # include #endif #include #include #include #include "ipsend.h" #if !defined(lint) static const char sccsid[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif /* * the code herein is dervied from libpcap. */ static u_char *buf = NULL; static int bufsize = 0, timeout = 1; int initdevice(char *device, int tout) { struct bpf_version bv; struct timeval to; struct ifreq ifr; #ifdef _PATH_BPF char *bpfname = _PATH_BPF; int fd; if ((fd = open(bpfname, O_RDWR)) < 0) { fprintf(stderr, "no bpf devices available as /dev/bpfxx\n"); - return -1; + return(-1); } #else char bpfname[16]; int fd = 0, i; for (i = 0; i < 16; i++) { (void) snprintf(bpfname, sizeof(bpfname), "/dev/bpf%d", i); if ((fd = open(bpfname, O_RDWR)) >= 0) break; } if (i == 16) { fprintf(stderr, "no bpf devices available as /dev/bpfxx\n"); - return -1; + return(-1); } #endif if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { perror("BIOCVERSION"); - return -1; + return(-1); } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { fprintf(stderr, "kernel bpf (v%d.%d) filter out of date:\n", bv.bv_major, bv.bv_minor); fprintf(stderr, "current version: %d.%d\n", BPF_MAJOR_VERSION, BPF_MINOR_VERSION); - return -1; + return(-1); } (void) strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, &ifr) == -1) { fprintf(stderr, "%s(%d):", ifr.ifr_name, fd); perror("BIOCSETIF"); exit(1); } /* * get kernel buffer size */ if (ioctl(fd, BIOCGBLEN, &bufsize) == -1) { perror("BIOCSBLEN"); exit(-1); } buf = (u_char*)malloc(bufsize); /* * set the timeout */ timeout = tout; to.tv_sec = 1; to.tv_usec = 0; if (ioctl(fd, BIOCSRTIMEOUT, (caddr_t)&to) == -1) { perror("BIOCSRTIMEOUT"); exit(-1); } (void) ioctl(fd, BIOCFLUSH, 0); - return fd; + return(fd); } /* * output an IP packet onto a fd opened for /dev/bpf */ int sendip(int fd, char *pkt, int len) { if (write(fd, pkt, len) == -1) { perror("send"); - return -1; + return(-1); } - return len; + return(len); } diff --git a/sbin/ipf/ipsend/sdlpi.c b/sbin/ipf/ipsend/sdlpi.c index 10ef87ed509d..91d46b1d0415 100644 --- a/sbin/ipf/ipsend/sdlpi.c +++ b/sbin/ipf/ipsend/sdlpi.c @@ -1,166 +1,166 @@ /* $FreeBSD$ */ /* * (C)opyright 1992-1998 Darren Reed. (from tcplog) * * See the IPFILTER.LICENCE file for details on licencing. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef sun # include # include #endif # include #include #include #include #include #include #include #include #include #include #include "ipsend.h" #if !defined(lint) static const char sccsid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #define CHUNKSIZE 8192 #define BUFSPACE (4*CHUNKSIZE) /* * Be careful to only include those defined in the flags option for the * interface are included in the header size. */ int initdevice(char *device, int tout) { char devname[16], *s, buf[256]; int i, fd; (void) strcpy(devname, "/dev/"); (void) strncat(devname, device, sizeof(devname) - strlen(devname)); s = devname + 5; while (*s && !ISDIGIT(*s)) s++; if (!*s) { fprintf(stderr, "bad device name %s\n", devname); exit(-1); } i = atoi(s); *s = '\0'; /* * For writing */ if ((fd = open(devname, O_RDWR)) < 0) { fprintf(stderr, "O_RDWR(1) "); perror(devname); exit(-1); } if (dlattachreq(fd, i) == -1) { fprintf(stderr, "dlattachreq: DLPI error\n"); exit(-1); } else if (dlokack(fd, buf) == -1) { fprintf(stderr, "dlokack(attach): DLPI error\n"); exit(-1); } #ifdef DL_HP_RAWDLS if (dlpromisconreq(fd, DL_PROMISC_SAP) < 0) { fprintf(stderr, "dlpromisconreq: DL_PROMISC_PHYS error\n"); exit(-1); } else if (dlokack(fd, buf) < 0) { fprintf(stderr, "dlokack(promisc): DLPI error\n"); exit(-1); } /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ dlbindreq(fd, 22, 1, DL_HP_RAWDLS, 0, 0); #else dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0); #endif dlbindack(fd, buf); /* * write full headers */ #ifdef DLIOCRAW /* we require RAW DLPI mode, which is a Sun extension */ if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1) { fprintf(stderr, "DLIOCRAW error\n"); exit(-1); } #endif - return fd; + return(fd); } /* * output an IP packet onto a fd opened for /dev/nit */ int sendip(int fd, char *pkt, int len) int fd, len; char *pkt; { struct strbuf dbuf, *dp = &dbuf, *cp = NULL; int pri = 0; #ifdef DL_HP_RAWDLS struct strbuf cbuf; dl_hp_rawdata_req_t raw; cp = &cbuf; raw.dl_primitive = DL_HP_RAWDATA_REQ; cp->len = sizeof(raw); cp->buf = (char *)&raw; cp->maxlen = cp->len; pri = MSG_HIPRI; #endif /* * construct NIT STREAMS messages, first control then data. */ dp->buf = pkt; dp->len = len; dp->maxlen = dp->len; if (putmsg(fd, cp, dp, pri) == -1) { perror("putmsg"); - return -1; + return(-1); } if (ioctl(fd, I_FLUSH, FLUSHW) == -1) { perror("I_FLUSHW"); - return -1; + return(-1); } - return len; + return(len); } diff --git a/sbin/ipf/ipsend/snit.c b/sbin/ipf/ipsend/snit.c index ae7491fcf54d..9c462341d1db 100644 --- a/sbin/ipf/ipsend/snit.c +++ b/sbin/ipf/ipsend/snit.c @@ -1,160 +1,160 @@ /* $FreeBSD$ */ /* * (C)opyright 1992-1998 Darren Reed. (from tcplog) * * See the IPFILTER.LICENCE file for details on licencing. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" #if !defined(lint) static const char sccsid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #define CHUNKSIZE 8192 #define BUFSPACE (4*CHUNKSIZE) /* * Be careful to only include those defined in the flags option for the * interface are included in the header size. */ #define BUFHDR_SIZE (sizeof(struct nit_bufhdr)) #define NIT_HDRSIZE (BUFHDR_SIZE) static int timeout; int initdevice(char *device, int tout) { struct strioctl si; struct timeval to; struct ifreq ifr; int fd; if ((fd = open("/dev/nit", O_RDWR)) < 0) { perror("/dev/nit"); exit(-1); } /* * arrange to get messages from the NIT STREAM and use NIT_BUF option */ ioctl(fd, I_SRDOPT, (char*)RMSGD); ioctl(fd, I_PUSH, "nbuf"); /* * set the timeout */ timeout = tout; si.ic_timout = 1; to.tv_sec = 1; to.tv_usec = 0; si.ic_cmd = NIOCSTIME; si.ic_len = sizeof(to); si.ic_dp = (char*)&to; if (ioctl(fd, I_STR, (char*)&si) == -1) { perror("ioctl: NIT timeout"); exit(-1); } /* * request the interface */ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' '; si.ic_cmd = NIOCBIND; si.ic_len = sizeof(ifr); si.ic_dp = (char*)𝔦 if (ioctl(fd, I_STR, (char*)&si) == -1) { perror(ifr.ifr_name); exit(1); } - return fd; + return(fd); } /* * output an IP packet onto a fd opened for /dev/nit */ int sendip(int fd, char *pkt, int len) int fd, len; char *pkt; { struct sockaddr sk, *sa = &sk; struct strbuf cbuf, *cp = &cbuf, dbuf, *dp = &dbuf; /* * For ethernet, need at least 802.3 header and IP header. */ if (len < (sizeof(sa->sa_data) + sizeof(struct ip))) - return -1; + return(-1); /* * to avoid any output processing for IP, say we're not. */ sa->sa_family = AF_UNSPEC; bcopy(pkt, sa->sa_data, sizeof(sa->sa_data)); pkt += sizeof(sa->sa_data); len -= sizeof(sa->sa_data); /* * construct NIT STREAMS messages, first control then data. */ cp->len = sizeof(*sa); cp->maxlen = sizeof(*sa); cp->buf = (char *)sa; dp->buf = pkt; dp->len = len; dp->maxlen = dp->len; if (putmsg(fd, cp, dp, 0) == -1) { perror("putmsg"); - return -1; + return(-1); } if (ioctl(fd, I_FLUSH, FLUSHW) == -1) { perror("I_FLUSH"); - return -1; + return(-1); } - return len; + return(len); } diff --git a/sbin/ipf/ipsend/sock.c b/sbin/ipf/ipsend/sock.c index 1104f51120fc..657c30303ce2 100644 --- a/sbin/ipf/ipsend/sock.c +++ b/sbin/ipf/ipsend/sock.c @@ -1,313 +1,313 @@ /* $FreeBSD$ */ /* * sock.c (C) 1995-1998 Darren Reed * * See the IPFILTER.LICENCE file for details on licencing. * */ #if !defined(lint) static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include #include #include #if defined(__NetBSD__) && defined(__vax__) /* * XXX need to declare boolean_t for _KERNEL * which ends up including for vax. See PR#32907 * for further details. */ typedef int boolean_t; #endif #include # include # ifdef __NetBSD__ # include # endif # ifdef __FreeBSD__ # define _WANT_FILE # else # define _KERNEL # define KERNEL # endif # include # ifdef __FreeBSD__ # undef _WANT_FILE # else # undef _KERNEL # undef KERNEL # endif #include #include #include #include #include # include #ifdef sun #include #include #endif #include #include #include #include #include #include #include #include #include # include #include #define _WANT_INPCB #include #include #define _WANT_TCPCB #include #include #include #include #include #include #include #include "ipsend.h" int nproc; struct proc *proc; #ifndef KMEM # ifdef _PATH_KMEM # define KMEM _PATH_KMEM # endif #endif #ifndef KERNEL # ifdef _PATH_UNIX # define KERNEL _PATH_UNIX # endif #endif #ifndef KMEM # define KMEM "/dev/kmem" #endif #ifndef KERNEL # define KERNEL "/vmunix" #endif static struct kinfo_proc *getproc(void); int kmemcpy(char *buf, void *pos, int n) { static int kfd = -1; off_t offset = (u_long)pos; if (kfd == -1) kfd = open(KMEM, O_RDONLY); if (lseek(kfd, offset, SEEK_SET) == -1) { perror("lseek"); - return -1; + return(-1); } if (read(kfd, buf, n) == -1) { perror("read"); - return -1; + return(-1); } - return n; + return(n); } struct nlist names[4] = { { "_proc" }, { "_nproc" }, { NULL }, { NULL } }; static struct kinfo_proc *getproc(void) { static struct kinfo_proc kp; pid_t pid = getpid(); int mib[4]; size_t n; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = pid; n = sizeof(kp); if (sysctl(mib, 4, &kp, &n, NULL, 0) == -1) { perror("sysctl"); - return NULL; + return(NULL); } - return &kp; + return(&kp); } struct tcpcb * find_tcp(int tfd, struct tcpiphdr *ti) { struct tcpcb *t; struct inpcb *i; struct socket *s; struct filedesc *fd; struct kinfo_proc *p; struct file *f, **o; if (!(p = getproc())) - return NULL; + return(NULL); fd = (struct filedesc *)malloc(sizeof(*fd)); if (fd == NULL) - return NULL; + return(NULL); #if defined( __FreeBSD__) if (KMCPY(fd, p->ki_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#lx,%#lx) failed\n", (u_long)p, (u_long)p->ki_fd); free(fd); - return NULL; + return(NULL); } #else if (KMCPY(fd, p->kp_proc.p_fd, sizeof(*fd)) == -1) { fprintf(stderr, "read(%#lx,%#lx) failed\n", (u_long)p, (u_long)p->kp_proc.p_fd); free(fd); - return NULL; + return(NULL); } #endif o = NULL; f = NULL; s = NULL; i = NULL; t = NULL; o = (struct file **)calloc(fd->fd_lastfile + 1, sizeof(*o)); if (KMCPY(o, fd->fd_ofiles, (fd->fd_lastfile + 1) * sizeof(*o)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%lu) - u_ofile - failed\n", (u_long)fd->fd_ofiles, (u_long)o, (u_long)sizeof(*o)); goto finderror; } f = (struct file *)calloc(1, sizeof(*f)); if (KMCPY(f, o[tfd], sizeof(*f)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%lu) - o[tfd] - failed\n", (u_long)o[tfd], (u_long)f, (u_long)sizeof(*f)); goto finderror; } s = (struct socket *)calloc(1, sizeof(*s)); if (KMCPY(s, f->f_data, sizeof(*s)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%lu) - f_data - failed\n", (u_long)f->f_data, (u_long)s, (u_long)sizeof(*s)); goto finderror; } i = (struct inpcb *)calloc(1, sizeof(*i)); if (KMCPY(i, s->so_pcb, sizeof(*i)) == -1) { fprintf(stderr, "kvm_read(%#lx,%#lx,%lu) - so_pcb - failed\n", (u_long)s->so_pcb, (u_long)i, (u_long)sizeof(*i)); goto finderror; } t = (struct tcpcb *)calloc(1, sizeof(*t)); if (KMCPY(t, i->inp_ppcb, sizeof(*t)) == -1) { fprintf(stderr, "read(%#lx,%#lx,%lu) - inp_ppcb - failed\n", (u_long)i->inp_ppcb, (u_long)t, (u_long)sizeof(*t)); goto finderror; } - return (struct tcpcb *)i->inp_ppcb; + return(struct tcpcb *)i->inp_ppcb; finderror: if (o != NULL) free(o); if (f != NULL) free(f); if (s != NULL) free(s); if (i != NULL) free(i); if (t != NULL) free(t); - return NULL; + return(NULL); } int do_socket(char *dev, int mtu, struct tcpiphdr *ti, struct in_addr gwip) { struct sockaddr_in rsin, lsin; struct tcpcb *t, tcb; int fd, nfd; socklen_t len; printf("Dest. Port: %d\n", ti->ti_dport); fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { perror("socket"); - return -1; + return(-1); } if (fcntl(fd, F_SETFL, FNDELAY) == -1) { perror("fcntl"); - return -1; + return(-1); } bzero((char *)&lsin, sizeof(lsin)); lsin.sin_family = AF_INET; bcopy((char *)&ti->ti_src, (char *)&lsin.sin_addr, sizeof(struct in_addr)); if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) == -1) { perror("bind"); - return -1; + return(-1); } len = sizeof(lsin); (void) getsockname(fd, (struct sockaddr *)&lsin, &len); ti->ti_sport = lsin.sin_port; printf("sport %d\n", ntohs(lsin.sin_port)); nfd = initdevice(dev, 1); if (nfd == -1) - return -1; + return(-1); if (!(t = find_tcp(fd, ti))) - return -1; + return(-1); bzero((char *)&rsin, sizeof(rsin)); rsin.sin_family = AF_INET; bcopy((char *)&ti->ti_dst, (char *)&rsin.sin_addr, sizeof(struct in_addr)); rsin.sin_port = ti->ti_dport; if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) == -1 && errno != EINPROGRESS) { perror("connect"); - return -1; + return(-1); } KMCPY(&tcb, t, sizeof(tcb)); ti->ti_win = tcb.rcv_adv; ti->ti_seq = tcb.snd_nxt - 1; ti->ti_ack = tcb.rcv_nxt; if (send_tcp(nfd, mtu, (ip_t *)ti, gwip) == -1) - return -1; + return(-1); (void)write(fd, "Hello World\n", 12); sleep(2); close(fd); - return 0; + return(0); } diff --git a/sbin/ipf/ipsend/sockraw.c b/sbin/ipf/ipsend/sockraw.c index 1fd04a91002b..441ed7934ba9 100644 --- a/sbin/ipf/ipsend/sockraw.c +++ b/sbin/ipf/ipsend/sockraw.c @@ -1,90 +1,90 @@ /* $FreeBSD$ */ /* * (C)opyright 2000 Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * WARNING: Attempting to use this .c file on HP-UX 11.00 will cause the * system to crash. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipsend.h" #if !defined(lint) && defined(LIBC_SCCS) static char sirix[] = "@(#)sirix.c 1.0 10/9/97 (C)1997 Marc Boucher"; #endif int initdevice(char *device, int tout) { struct sockaddr s; struct ifreq ifr; int fd; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name); if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("socket(AF_INET, SOCK_RAW, IPPROTO_RAW)"); - return -1; + return(-1); } if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { perror("ioctl SIOCGIFADDR"); - return -1; + return(-1); } bzero((char *)&s, sizeof(s)); s.sa_family = AF_INET; bcopy(&ifr.ifr_addr, s.sa_data, 4); if (bind(fd, &s, sizeof(s)) == -1) perror("bind"); - return fd; + return(fd); } /* * output an IP packet */ int sendip(int fd, char *pkt, int len) { struct ether_header *eh; struct sockaddr_in sin; eh = (struct ether_header *)pkt; bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; pkt += 14; len -= 14; bcopy(pkt + 12, (char *)&sin.sin_addr, 4); if (sendto(fd, pkt, len, 0, &sin, sizeof(sin)) == -1) { perror("send"); - return -1; + return(-1); } - return len; + return(len); } diff --git a/sbin/ipf/libipf/addipopt.c b/sbin/ipf/libipf/addipopt.c index 81429fbb84b7..cc212a0b8ca7 100644 --- a/sbin/ipf/libipf/addipopt.c +++ b/sbin/ipf/libipf/addipopt.c @@ -1,62 +1,62 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int addipopt(char *op, struct ipopt_names *io, int len, char *class) { int olen = len; struct in_addr ipadr; u_short val; u_char lvl; char *s; if ((len + io->on_siz) > 48) { fprintf(stderr, "options too long\n"); - return 0; + return(0); } len += io->on_siz; *op++ = io->on_value; if (io->on_siz > 1) { s = op; *op++ = io->on_siz; *op++ = IPOPT_MINOFF; if (class) { switch (io->on_value) { case IPOPT_SECURITY : lvl = seclevel(class); *(op - 1) = lvl; break; case IPOPT_RR : case IPOPT_TS : s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; break; case IPOPT_LSRR : case IPOPT_SSRR : ipadr.s_addr = inet_addr(class); s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; bcopy((char *)&ipadr, op, sizeof(ipadr)); break; case IPOPT_SATID : val = atoi(class); bcopy((char *)&val, op, 2); break; } } } if (opts & OPT_DEBUG) fprintf(stderr, "bo: %s %d %#x: %d\n", io->on_name, io->on_value, io->on_bit, len); - return len - olen; + return(len - olen); } diff --git a/sbin/ipf/libipf/alist_new.c b/sbin/ipf/libipf/alist_new.c index 73bc03073990..05f691a562b9 100644 --- a/sbin/ipf/libipf/alist_new.c +++ b/sbin/ipf/libipf/alist_new.c @@ -1,93 +1,93 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: alist_new.c,v 1.5.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" #include alist_t * alist_new(int family, char *host) { int a, b, c, d, bits; char *slash; alist_t *al; u_int mask; if (family == AF_UNSPEC) { if (strchr(host, ':') != NULL) family = AF_INET6; else family = AF_INET; } if (family != AF_INET && family != AF_INET6) - return NULL; + return(NULL); al = calloc(1, sizeof(*al)); if (al == NULL) { fprintf(stderr, "alist_new out of memory\n"); - return NULL; + return(NULL); } while (ISSPACE(*host)) host++; if (*host == '!') { al->al_not = 1; host++; while (ISSPACE(*host)) host++; } bits = -1; slash = strchr(host, '/'); if (slash != NULL) { *slash = '\0'; bits = atoi(slash + 1); } if (family == AF_INET) { if (bits > 32) goto bad; a = b = c = d = -1; sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d); if (bits > 0 && bits < 33) { mask = 0xffffffff << (32 - bits); } else if (b == -1) { mask = 0xff000000; b = c = d = 0; } else if (c == -1) { mask = 0xffff0000; c = d = 0; } else if (d == -1) { mask = 0xffffff00; d = 0; } else { mask = 0xffffffff; } al->al_mask = htonl(mask); } else { if (bits > 128) goto bad; fill6bits(bits, al->al_i6mask.i6); } if (gethost(family, host, &al->al_i6addr) == -1) { if (slash != NULL) *slash = '/'; fprintf(stderr, "Cannot parse hostname\n"); goto bad; } al->al_family = family; if (slash != NULL) *slash = '/'; - return al; + return(al); bad: free(al); - return NULL; + return(NULL); } diff --git a/sbin/ipf/libipf/allocmbt.c b/sbin/ipf/libipf/allocmbt.c index ec00cb09b31e..23c835a8190c 100644 --- a/sbin/ipf/libipf/allocmbt.c +++ b/sbin/ipf/libipf/allocmbt.c @@ -1,23 +1,23 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: allocmbt.c,v 1.1.4.1 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" mb_t * allocmbt(size_t len) { mb_t *m; m = (mb_t *)malloc(sizeof(mb_t)); if (m == NULL) - return NULL; + return(NULL); m->mb_len = len; m->mb_next = NULL; m->mb_data = (char *)m->mb_buf; - return m; + return(m); } diff --git a/sbin/ipf/libipf/bcopywrap.c b/sbin/ipf/libipf/bcopywrap.c index c704ef04e5ee..fbe6fd4a8250 100644 --- a/sbin/ipf/libipf/bcopywrap.c +++ b/sbin/ipf/libipf/bcopywrap.c @@ -1,19 +1,19 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int bcopywrap(void *from, void *to, size_t size) { bcopy((caddr_t)from, (caddr_t)to, size); - return 0; + return(0); } diff --git a/sbin/ipf/libipf/buildopts.c b/sbin/ipf/libipf/buildopts.c index 2f16fcda049b..3e06a4cf0fc8 100644 --- a/sbin/ipf/libipf/buildopts.c +++ b/sbin/ipf/libipf/buildopts.c @@ -1,49 +1,49 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" u_32_t buildopts(char *cp, char *op, int len) { struct ipopt_names *io; u_32_t msk = 0; char *s, *t; int inc; for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { if ((t = strchr(s, '='))) *t++ = '\0'; else t = ""; for (io = ionames; io->on_name; io++) { if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) continue; if ((inc = addipopt(op, io, len, t))) { op += inc; len += inc; } msk |= io->on_bit; break; } if (!io->on_name) { fprintf(stderr, "unknown IP option name %s\n", s); - return 0; + return(0); } } while ((len & 3) != 3) { *op++ = IPOPT_NOP; len++; } *op++ = IPOPT_EOL; len++; - return len; + return(len); } diff --git a/sbin/ipf/libipf/checkrev.c b/sbin/ipf/libipf/checkrev.c index 6f73ec0c9573..6673eb296495 100644 --- a/sbin/ipf/libipf/checkrev.c +++ b/sbin/ipf/libipf/checkrev.c @@ -1,46 +1,46 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ipl.h" int checkrev(char *ipfname) { static int vfd = -1; struct friostat fio; ipfobj_t obj; bzero((caddr_t)&obj, sizeof(obj)); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_size = sizeof(fio); obj.ipfo_ptr = (void *)&fio; obj.ipfo_type = IPFOBJ_IPFSTAT; if ((vfd == -1) && ((vfd = open(ipfname, O_RDONLY)) == -1)) { perror("open device"); - return -1; + return(-1); } if (ioctl(vfd, SIOCGETFS, &obj)) { ipferror(vfd, "ioctl(SIOCGETFS)"); close(vfd); vfd = -1; - return -1; + return(-1); } if (strncmp(IPL_VERSION, fio.f_version, sizeof(fio.f_version))) { - return -1; + return(-1); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/connecttcp.c b/sbin/ipf/libipf/connecttcp.c index 2bab2afe0daa..bbfb867877cf 100644 --- a/sbin/ipf/libipf/connecttcp.c +++ b/sbin/ipf/libipf/connecttcp.c @@ -1,48 +1,48 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: connecttcp.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" #include /* * Format expected is one addres per line, at the start of each line. */ int connecttcp(char *server, int port) { struct sockaddr_in sin; struct hostent *host; int fd; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port & 65535); if (ISDIGIT(*server)) { if (inet_aton(server, &sin.sin_addr) == -1) { - return -1; + return(-1); } } else { host = gethostbyname(server); if (host == NULL) - return -1; + return(-1); memcpy(&sin.sin_addr, host->h_addr_list[0], sizeof(sin.sin_addr)); } fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) - return -1; + return(-1); if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { close(fd); - return -1; + return(-1); } - return fd; + return(fd); } diff --git a/sbin/ipf/libipf/count4bits.c b/sbin/ipf/libipf/count4bits.c index f374928e7b0e..495a8044d62f 100644 --- a/sbin/ipf/libipf/count4bits.c +++ b/sbin/ipf/libipf/count4bits.c @@ -1,40 +1,40 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" /* * count consecutive 1's in bit mask. If the mask generated by counting - * consecutive 1's is different to that passed, return -1, else return # +* consecutive 1's is different to that passed, return -1, else return # * of bits. */ int count4bits(u_int ip) { int cnt = 0, i, j; u_int ipn; ip = ipn = ntohl(ip); for (i = 32; i; i--, ipn *= 2) if (ipn & 0x80000000) cnt++; else break; ipn = 0; for (i = 32, j = cnt; i; i--, j--) { ipn *= 2; if (j > 0) ipn++; } if (ipn == ip) - return cnt; - return -1; + return(cnt); + return(-1); } diff --git a/sbin/ipf/libipf/count6bits.c b/sbin/ipf/libipf/count6bits.c index ba624f4d8719..f0b5fb239206 100644 --- a/sbin/ipf/libipf/count6bits.c +++ b/sbin/ipf/libipf/count6bits.c @@ -1,29 +1,29 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int count6bits(u_32_t *msk) { int i = 0, k; u_32_t j; for (k = 3; k >= 0; k--) if (msk[k] == 0xffffffff) i += 32; else { for (j = msk[k]; j; j <<= 1) if (j & 0x80000000) i++; } - return i; + return(i); } diff --git a/sbin/ipf/libipf/dupmbt.c b/sbin/ipf/libipf/dupmbt.c index 5a009d8e5a62..b25bb70809cc 100644 --- a/sbin/ipf/libipf/dupmbt.c +++ b/sbin/ipf/libipf/dupmbt.c @@ -1,24 +1,24 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: dupmbt.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" mb_t * dupmbt(mb_t *orig) { mb_t *m; m = (mb_t *)malloc(sizeof(mb_t)); if (m == NULL) - return NULL; + return(NULL); m->mb_len = orig->mb_len; m->mb_next = NULL; m->mb_data = (char *)m->mb_buf + (orig->mb_data - (char *)orig->mb_buf); bcopy(orig->mb_data, m->mb_data, m->mb_len); - return m; + return(m); } diff --git a/sbin/ipf/libipf/facpri.c b/sbin/ipf/libipf/facpri.c index d892050f20d9..b38282b422c9 100644 --- a/sbin/ipf/libipf/facpri.c +++ b/sbin/ipf/libipf/facpri.c @@ -1,149 +1,149 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #endif #include #include #include #include #include "facpri.h" #if !defined(lint) static const char rcsid[] = "@(#)$Id$"; #endif typedef struct table { char *name; int value; } table_t; table_t facs[] = { { "kern", LOG_KERN }, { "user", LOG_USER }, { "mail", LOG_MAIL }, { "daemon", LOG_DAEMON }, { "auth", LOG_AUTH }, { "syslog", LOG_SYSLOG }, { "lpr", LOG_LPR }, { "news", LOG_NEWS }, { "uucp", LOG_UUCP }, #if LOG_CRON == LOG_CRON2 { "cron2", LOG_CRON1 }, #else { "cron", LOG_CRON1 }, #endif #ifdef LOG_FTP { "ftp", LOG_FTP }, #endif #ifdef LOG_AUTHPRIV { "authpriv", LOG_AUTHPRIV }, #endif #ifdef LOG_AUDIT { "audit", LOG_AUDIT }, #endif #ifdef LOG_LFMT { "logalert", LOG_LFMT }, #endif #if LOG_CRON == LOG_CRON1 { "cron", LOG_CRON2 }, #else { "cron2", LOG_CRON2 }, #endif #ifdef LOG_SECURITY { "security", LOG_SECURITY }, #endif { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { NULL, 0 } }; /* * map a facility number to its name */ char * fac_toname(int facpri) { int i, j, fac; fac = facpri & LOG_FACMASK; j = fac >> 3; if (j < (sizeof(facs)/sizeof(facs[0]))) { if (facs[j].value == fac) - return facs[j].name; + return(facs[j].name); } for (i = 0; facs[i].name; i++) if (fac == facs[i].value) - return facs[i].name; + return(facs[i].name); - return NULL; + return(NULL); } /* * map a facility name to its number */ int fac_findname(char *name) { int i; for (i = 0; facs[i].name; i++) if (!strcmp(facs[i].name, name)) - return facs[i].value; - return -1; + return(facs[i].value); + return(-1); } table_t pris[] = { { "emerg", LOG_EMERG }, { "alert", LOG_ALERT }, { "crit", LOG_CRIT }, { "err", LOG_ERR }, { "warn", LOG_WARNING }, { "notice", LOG_NOTICE }, { "info", LOG_INFO }, { "debug", LOG_DEBUG }, { NULL, 0 } }; /* * map a facility name to its number */ int pri_findname(char *name) { int i; for (i = 0; pris[i].name; i++) if (!strcmp(pris[i].name, name)) - return pris[i].value; - return -1; + return(pris[i].value); + return(-1); } /* * map a priority number to its name */ char * pri_toname(int facpri) { int i, pri; pri = facpri & LOG_PRIMASK; if (pris[pri].value == pri) - return pris[pri].name; + return(pris[pri].name); for (i = 0; pris[i].name; i++) if (pri == pris[i].value) - return pris[i].name; - return NULL; + return(pris[i].name); + return(NULL); } diff --git a/sbin/ipf/libipf/familyname.c b/sbin/ipf/libipf/familyname.c index 10cd0eaa1e83..d8d8af3d2a00 100644 --- a/sbin/ipf/libipf/familyname.c +++ b/sbin/ipf/libipf/familyname.c @@ -1,13 +1,13 @@ #include "ipf.h" const char * familyname(int family) { if (family == AF_INET) - return "inet"; + return("inet"); #ifdef USE_INET6 if (family == AF_INET6) - return "inet6"; + return("inet6"); #endif - return "unknown"; + return("unknown"); } diff --git a/sbin/ipf/libipf/findword.c b/sbin/ipf/libipf/findword.c index 8e836267db22..5a2905ed7c6f 100644 --- a/sbin/ipf/libipf/findword.c +++ b/sbin/ipf/libipf/findword.c @@ -1,24 +1,24 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: findword.c,v 1.3.4.1 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" wordtab_t * findword(wordtab_t *words, char *name) { wordtab_t *w; for (w = words; w->w_word != NULL; w++) if (!strcmp(name, w->w_word)) break; if (w->w_word == NULL) - return NULL; + return(NULL); - return w; + return(w); } diff --git a/sbin/ipf/libipf/ftov.c b/sbin/ipf/libipf/ftov.c index 082a50e1c397..bf5d535894e0 100644 --- a/sbin/ipf/libipf/ftov.c +++ b/sbin/ipf/libipf/ftov.c @@ -1,15 +1,15 @@ #include "ipf.h" int ftov(int version) { #ifdef USE_INET6 if (version == AF_INET6) - return 6; + return(6); #endif if (version == AF_INET) - return 4; + return(4); if (version == AF_UNSPEC) - return 0; - return -1; + return(0); + return(-1); } diff --git a/sbin/ipf/libipf/gethost.c b/sbin/ipf/libipf/gethost.c index a66247701683..6c889fe1c7aa 100644 --- a/sbin/ipf/libipf/gethost.c +++ b/sbin/ipf/libipf/gethost.c @@ -1,74 +1,74 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int gethost(int family, char *name, i6addr_t *hostp) { struct hostent *h; struct netent *n; u_32_t addr; bzero(hostp, sizeof(*hostp)); if (!strcmp(name, "test.host.dots")) { if (family == AF_INET) { hostp->in4.s_addr = htonl(0xfedcba98); } #ifdef USE_INET6 if (family == AF_INET6) { hostp->i6[0] = htonl(0xfe80aa55); hostp->i6[1] = htonl(0x12345678); hostp->i6[2] = htonl(0x5a5aa5a5); hostp->i6[3] = htonl(0xfedcba98); } #endif - return 0; + return(0); } if (!strcmp(name, "")) name = thishost; if (family == AF_INET) { h = gethostbyname(name); if (h != NULL) { if ((h->h_addr != NULL) && (h->h_length == sizeof(addr))) { bcopy(h->h_addr, (char *)&addr, sizeof(addr)); hostp->in4.s_addr = addr; - return 0; + return(0); } } n = getnetbyname(name); if (n != NULL) { hostp->in4.s_addr = htonl(n->n_net & 0xffffffff); - return 0; + return(0); } } #ifdef USE_INET6 if (family == AF_INET6) { struct addrinfo hints, *res; struct sockaddr_in6 *sin6; bzero((char *)&hints, sizeof(hints)); hints.ai_family = PF_INET6; getaddrinfo(name, NULL, &hints, &res); if (res != NULL) { sin6 = (struct sockaddr_in6 *)res->ai_addr; hostp->in6 = sin6->sin6_addr; freeaddrinfo(res); - return 0; + return(0); } } #endif - return -1; + return(-1); } diff --git a/sbin/ipf/libipf/geticmptype.c b/sbin/ipf/libipf/geticmptype.c index aa62d0a41909..4705b43ce7ac 100644 --- a/sbin/ipf/libipf/geticmptype.c +++ b/sbin/ipf/libipf/geticmptype.c @@ -1,28 +1,28 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int geticmptype(int family, char *name) { icmptype_t *i; for (i = icmptypelist; i->it_name != NULL; i++) { if (!strcmp(name, i->it_name)) { if (family == AF_INET) - return i->it_v4; + return(i->it_v4); #ifdef USE_INET6 if (family == AF_INET6) - return i->it_v6; + return(i->it_v6); #endif - return -1; + return(-1); } } - return -1; + return(-1); } diff --git a/sbin/ipf/libipf/getifname.c b/sbin/ipf/libipf/getifname.c index beb3795fbbb9..13cde4f51139 100644 --- a/sbin/ipf/libipf/getifname.c +++ b/sbin/ipf/libipf/getifname.c @@ -1,54 +1,54 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include "kmem.h" /* - * Given a pointer to an interface in the kernel, return a pointer to a +* Given a pointer to an interface in the kernel, return a pointer to a * string which is the interface name. */ char * getifname(struct ifnet *ptr) { #if SOLARIS # include # include # include "../pfil/qif.h" char *ifname; qif_t qif; if ((void *)ptr == (void *)-1) - return "!"; + return("!"); if (ptr == NULL) - return "-"; + return("-"); if (kmemcpy((char *)&qif, (u_long)ptr, sizeof(qif)) == -1) - return "X"; + return("X"); ifname = strdup(qif.qf_name); if ((ifname != NULL) && (*ifname == '\0')) { free(ifname); - return "!"; + return("!"); } - return ifname; + return(ifname); #else struct ifnet netif; if ((void *)ptr == (void *)-1) - return "!"; + return("!"); if (ptr == NULL) - return "-"; + return("-"); if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1) - return "X"; - return strdup(netif.if_xname); + return("X"); + return(strdup(netif.if_xname)); #endif } diff --git a/sbin/ipf/libipf/getnattype.c b/sbin/ipf/libipf/getnattype.c index 44e1134a7f06..c5f5d3fd777b 100644 --- a/sbin/ipf/libipf/getnattype.c +++ b/sbin/ipf/libipf/getnattype.c @@ -1,69 +1,69 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) */ #include "ipf.h" #include "kmem.h" #if !defined(lint) static const char rcsid[] = "@(#)$Id$"; #endif /* * Get a nat filter type given its kernel address. */ char * getnattype(nat_t *nat) { static char unknownbuf[20]; char *which; if (!nat) - return "???"; + return("???"); switch (nat->nat_redir) { case NAT_MAP : which = "MAP"; break; case NAT_MAPBLK : which = "MAP-BLOCK"; break; case NAT_REDIRECT : which = "RDR"; break; case NAT_MAP|NAT_REWRITE : which = "RWR-MAP"; break; case NAT_REDIRECT|NAT_REWRITE : which = "RWR-RDR"; break; case NAT_BIMAP : which = "BIMAP"; break; case NAT_REDIRECT|NAT_DIVERTUDP : which = "DIV-RDR"; break; case NAT_MAP|NAT_DIVERTUDP : which = "DIV-MAP"; break; case NAT_REDIRECT|NAT_ENCAP : which = "ENC-RDR"; break; case NAT_MAP|NAT_ENCAP : which = "ENC-MAP"; break; default : snprintf(unknownbuf, sizeof(unknownbuf), "unknown(%04x)", nat->nat_redir & 0xffffffff); which = unknownbuf; break; } - return which; + return(which); } diff --git a/sbin/ipf/libipf/getport.c b/sbin/ipf/libipf/getport.c index d2a4ba7f9c1f..4b1471a4b67f 100644 --- a/sbin/ipf/libipf/getport.c +++ b/sbin/ipf/libipf/getport.c @@ -1,88 +1,88 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include int getport(frentry_t *fr, char *name, u_short *port, char *proto) { struct protoent *p; struct servent *s; u_short p1; if (fr == NULL || fr->fr_type != FR_T_IPF) { s = getservbyname(name, proto); if (s != NULL) { *port = s->s_port; - return 0; + return(0); } if (ISDIGIT(*name)) { int portval = atoi(name); if (portval < 0 || portval > 65535) - return -1; + return(-1); *port = htons((u_short)portval); - return 0; + return(0); } - return -1; + return(-1); } /* * Some people will use port names in rules without specifying * either TCP or UDP because it is implied by the group head. * If we don't know the protocol, then the best we can do here is * to take either only the TCP or UDP mapping (if one or the other * is missing) or make sure both of them agree. */ if (fr->fr_proto == 0) { s = getservbyname(name, "tcp"); if (s != NULL) p1 = s->s_port; else p1 = 0; s = getservbyname(name, "udp"); if (s != NULL) { if (p1 != s->s_port) - return -1; + return(-1); } if ((p1 == 0) && (s == NULL)) - return -1; + return(-1); if (p1) *port = p1; else *port = s->s_port; - return 0; + return(0); } if ((fr->fr_flx & FI_TCPUDP) != 0) { /* * If a rule is "tcp/udp" then check that both TCP and UDP * mappings for this protocol name match ports. */ s = getservbyname(name, "tcp"); if (s == NULL) - return -1; + return(-1); p1 = s->s_port; s = getservbyname(name, "udp"); if (s == NULL || s->s_port != p1) - return -1; + return(-1); *port = p1; - return 0; + return(0); } p = getprotobynumber(fr->fr_proto); s = getservbyname(name, p ? p->p_name : NULL); if (s != NULL) { *port = s->s_port; - return 0; + return(0); } - return -1; + return(-1); } diff --git a/sbin/ipf/libipf/getportproto.c b/sbin/ipf/libipf/getportproto.c index 7835748175b7..2119f98f2000 100644 --- a/sbin/ipf/libipf/getportproto.c +++ b/sbin/ipf/libipf/getportproto.c @@ -1,39 +1,39 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include "ipf.h" int getportproto(char *name, int proto) { struct servent *s; struct protoent *p; if (ISDIGIT(*name)) { int number; char *s; for (s = name; *s != '\0'; s++) if (!ISDIGIT(*s)) - return -1; + return(-1); number = atoi(name); if (number < 0 || number > 65535) - return -1; - return htons(number); + return(-1); + return(htons(number)); } p = getprotobynumber(proto); s = getservbyname(name, p ? p->p_name : NULL); if (s != NULL) - return s->s_port; - return -1; + return(s->s_port); + return(-1); } diff --git a/sbin/ipf/libipf/getproto.c b/sbin/ipf/libipf/getproto.c index 5432a60434f3..2009941eec0d 100644 --- a/sbin/ipf/libipf/getproto.c +++ b/sbin/ipf/libipf/getproto.c @@ -1,35 +1,35 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include int getproto(char *name); int getproto(char *name) { struct protoent *p; char *s; for (s = name; *s != '\0'; s++) if (!ISDIGIT(*s)) break; if (*s == '\0') - return atoi(name); + return(atoi(name)); if (!strcasecmp(name, "ip")) - return 0; + return(0); p = getprotobyname(name); if (p != NULL) - return p->p_proto; - return -1; + return(p->p_proto); + return(-1); } diff --git a/sbin/ipf/libipf/getsumd.c b/sbin/ipf/libipf/getsumd.c index d353e1189e34..73999893277e 100644 --- a/sbin/ipf/libipf/getsumd.c +++ b/sbin/ipf/libipf/getsumd.c @@ -1,23 +1,23 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" char * getsumd(u_32_t sum) { static char sumdbuf[17]; if (sum & NAT_HW_CKSUM) snprintf(sumdbuf, sizeof(sumdbuf), "hw(%#0x)", sum & 0xffff); else snprintf(sumdbuf, sizeof(sumdbuf), "%#0x", sum); - return sumdbuf; + return(sumdbuf); } diff --git a/sbin/ipf/libipf/hostname.c b/sbin/ipf/libipf/hostname.c index 3b179954bbff..d6f3f87ac75c 100644 --- a/sbin/ipf/libipf/hostname.c +++ b/sbin/ipf/libipf/hostname.c @@ -1,59 +1,59 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" char * hostname(int family, void *ip) { static char hostbuf[MAXHOSTNAMELEN+1]; struct hostent *hp; struct in_addr ipa; struct netent *np; memset(&ipa, 0, sizeof(ipa)); /* XXX gcc */ if (family == AF_INET) { ipa.s_addr = *(u_32_t *)ip; if (ipa.s_addr == htonl(0xfedcba98)) - return ("test.host.dots"); + return("test.host.dots"); } if ((opts & OPT_NORESOLVE) == 0) { if (family == AF_INET) { hp = gethostbyaddr(ip, 4, AF_INET); if (hp != NULL && hp->h_name != NULL && *hp->h_name != '\0') { strncpy(hostbuf, hp->h_name, sizeof(hostbuf)); hostbuf[sizeof(hostbuf) - 1] = '\0'; - return (hostbuf); + return(hostbuf); } np = getnetbyaddr(ipa.s_addr, AF_INET); if (np != NULL && np->n_name != NULL && *np->n_name != '\0') { strncpy(hostbuf, np->n_name, sizeof(hostbuf)); hostbuf[sizeof(hostbuf) - 1] = '\0'; - return (hostbuf); + return(hostbuf); } } } if (family == AF_INET) { - return (inet_ntoa(ipa)); + return(inet_ntoa(ipa)); } #ifdef USE_INET6 (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); hostbuf[MAXHOSTNAMELEN] = '\0'; - return (hostbuf); + return(hostbuf); #else - return ("IPv6"); + return("IPv6"); #endif } diff --git a/sbin/ipf/libipf/icmptypename.c b/sbin/ipf/libipf/icmptypename.c index 304b902a00e5..f94a7e5f8a0b 100644 --- a/sbin/ipf/libipf/icmptypename.c +++ b/sbin/ipf/libipf/icmptypename.c @@ -1,28 +1,28 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" char * icmptypename(int family, int type) { icmptype_t *i; if ((type < 0) || (type > 255)) - return NULL; + return(NULL); for (i = icmptypelist; i->it_name != NULL; i++) { if ((family == AF_INET) && (i->it_v4 == type)) - return i->it_name; + return(i->it_name); #ifdef USE_INET6 if ((family == AF_INET6) && (i->it_v6 == type)) - return i->it_name; + return(i->it_name); #endif } - return NULL; + return(NULL); } diff --git a/sbin/ipf/libipf/inet_addr.c b/sbin/ipf/libipf/inet_addr.c index 0a29c775b964..c5c745ee58d9 100644 --- a/sbin/ipf/libipf/inet_addr.c +++ b/sbin/ipf/libipf/inet_addr.c @@ -1,201 +1,201 @@ /* $FreeBSD$ */ /* * ++Copyright++ 1983, 1990, 1993 * - * Copyright (c) 1983, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. * - * --Copyright-- */ #if !defined(lint) static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.8.2.3 2004/12/09 19:41:20 darrenr Exp $"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #ifndef __P # define __P(x) x #endif int inet_aton(const char *, struct in_addr *); /* * Because the ctype(3) posix definition, if used "safely" in code everywhere, * would mean all normal code that walks through strings needed casts. Yuck. */ #define ISALNUM(x) isalnum((u_char)(x)) #define ISALPHA(x) isalpha((u_char)(x)) #define ISASCII(x) isascii((u_char)(x)) #define ISDIGIT(x) isdigit((u_char)(x)) #define ISPRINT(x) isprint((u_char)(x)) #define ISSPACE(x) isspace((u_char)(x)) #define ISUPPER(x) isupper((u_char)(x)) #define ISXDIGIT(x) isxdigit((u_char)(x)) #define ISLOWER(x) islower((u_char)(x)) /* * Check whether "cp" is a valid ascii representation * of an Internet address and convert to a binary address. * Returns 1 if the address is valid, 0 if not. - * This replaces inet_addr, the return value from which +* This replaces inet_addr, the return value from which * cannot distinguish between failure and a local broadcast address. */ int inet_aton(register const char *cp, struct in_addr *addr) { register u_long val; register int base, n; register char c; u_int parts[4]; register u_int *pp = parts; c = *cp; for (;;) { /* * Collect number up to ``.''. * Values are specified as for C: * 0x=hex, 0=octal, isdigit=decimal. */ if (!ISDIGIT(c)) - return (0); + return(0); val = 0; base = 10; if (c == '0') { c = *++cp; if (c == 'x' || c == 'X') base = 16, c = *++cp; else base = 8; } for (;;) { if (ISASCII(c) && ISDIGIT(c)) { val = (val * base) + (c - '0'); c = *++cp; } else if (base == 16 && ISASCII(c) && ISXDIGIT(c)) { val = (val << 4) | (c + 10 - (ISLOWER(c) ? 'a' : 'A')); c = *++cp; } else break; } if (c == '.') { /* * Internet format: * a.b.c.d * a.b.c (with c treated as 16 bits) * a.b (with b treated as 24 bits) */ if (pp >= parts + 3) - return (0); + return(0); *pp++ = val; c = *++cp; } else break; } /* * Check for trailing characters. */ if (c != '\0' && (!ISASCII(c) || !ISSPACE(c))) - return (0); + return(0); /* * Concoct the address according to * the number of parts specified. */ n = pp - parts + 1; switch (n) { case 0: - return (0); /* initial nondigit */ + return(0); /* initial nondigit */ case 1: /* a -- 32 bits */ break; case 2: /* a.b -- 8.24 bits */ if (val > 0xffffff) - return (0); + return(0); val |= parts[0] << 24; break; case 3: /* a.b.c -- 8.8.16 bits */ if (val > 0xffff) - return (0); + return(0); val |= (parts[0] << 24) | (parts[1] << 16); break; case 4: /* a.b.c.d -- 8.8.8.8 bits */ if (val > 0xff) - return (0); + return(0); val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); break; } if (addr) addr->s_addr = htonl(val); - return (1); + return(1); } /* these are compatibility routines, not needed on recent BSD releases */ /* * Ascii internet address interpretation routine. * The value returned is in network order. */ #if 0 inet_addr(const char *cp) { struct in_addr val; if (inet_aton(cp, &val)) - return (val.s_addr); - return (0xffffffff); + return(val.s_addr); + return(0xffffffff); } #endif diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c index c6e2e3dc03c3..5205e215a48c 100644 --- a/sbin/ipf/libipf/interror.c +++ b/sbin/ipf/libipf/interror.c @@ -1,578 +1,578 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: interror.c,v 1.9.2.12 2012/07/22 08:03:39 darren_r Exp $ */ #include "ipf.h" #include #include typedef struct { int iee_number; char *iee_text; } ipf_error_entry_t; static ipf_error_entry_t *find_error(int); #define IPF_NUM_ERRORS 475 /* * NO REUSE OF NUMBERS! * * IF YOU WANT TO ADD AN ERROR TO THIS TABLE, _ADD_ A NEW NUMBER. * DO _NOT_ USE AN EMPTY NUMBER OR FILL IN A GAP. */ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = { { 1, "auth table locked/full" }, { 2, "" }, { 3, "copyinptr received bad address" }, { 4, "copyoutptr received bad address" }, { 5, "" }, { 6, "cannot load a rule with FR_T_BUILTIN flag set" }, { 7, "internal rule without FR_T_BUILDINT flag set" }, { 8, "no data provided with filter rule" }, { 9, "invalid ioctl for rule" }, { 10, "rule protocol is not 4 or 6" }, { 11, "cannot find rule function" }, { 12, "cannot find rule group" }, { 13, "group in/out does not match rule in/out" }, { 14, "rule without in/out does not belong to a group" }, { 15, "cannot determine where to append rule" }, { 16, "malloc for rule data failed" }, { 17, "copyin for rule data failed" }, { 18, "" }, { 19, "zero data size for BPF rule" }, { 20, "BPF validation failed" }, { 21, "incorrect data size for IPF rule" }, { 22, "'keep state' rule included 'with oow'" }, { 23, "bad interface index with dynamic source address" }, { 24, "bad interface index with dynamic dest. address" }, { 25, "match array verif failed for filter rule" }, { 26, "bad filter rule type" }, { 27, "rule not found for zero'stats" }, { 28, "copyout failed for zero'ing stats" }, { 29, "rule not found for removing" }, { 30, "cannot remove internal rule" }, { 31, "rule in use" }, { 32, "rule already exists" }, { 33, "no memory for another rule" }, { 34, "could not find function" }, { 35, "copyout failed for resolving function name -> addr" }, { 36, "copyout failed for resolving function addr -> name" }, { 37, "function name/addr resolving search failed" }, { 38, "group map cannot find it's hash table" }, { 39, "group map hash-table in/out do not match rule" }, { 40, "bcopyout failed for SIOCIPFINTERROR" }, { 41, "" }, { 42, "ipfilter not enabled for NAT ioctl" }, { 43, "ipfilter not enabled for state ioctl" }, { 44, "ipfilter not enabled for auth ioctl" }, { 45, "ipfilter not enbaled for sync ioctl" }, { 46, "ipfilter not enabled for scan ioctl" }, { 47, "ipfilter not enabled for lookup ioctl" }, { 48, "unrecognised device minor number for ioctl" }, { 49, "unrecognised object type for copying in ipfobj" }, { 50, "mismatching object type for copying in ipfobj" }, { 51, "object size too small for copying in ipfobj" }, { 52, "object size mismatch for copying in ipfobj" }, { 53, "compat object size too small for copying in ipfobj" }, { 54, "compat object size mismatch for copying in ipfobj" }, { 55, "error doing copyin of data for in ipfobj" }, { 56, "unrecognised object type for size copy in ipfobj" }, { 57, "object size too small for size copy in ipfobj" }, { 58, "mismatching object type for size copy in ipfobj" }, { 59, "object size mismatch for size copy in ipfobj" }, { 60, "compat object size mismatch for size copy in ipfobj" }, { 61, "error doing size copyin of data for in ipfobj" }, { 62, "bad object type for size copy out ipfobj" }, { 63, "mismatching object type for size copy out ipfobj" }, { 64, "object size mismatch for size copy out ipfobj" }, { 65, "compat object size wrong for size copy out ipfobj" }, { 66, "error doing size copyout of data for out ipfobj" }, { 67, "unrecognised object type for copying out ipfobj" }, { 68, "mismatching object type for copying out ipfobj" }, { 69, "object size too small for copying out ipfobj" }, { 70, "object size mismatch for copying out ipfobj" }, { 71, "compat object size too small for copying out ipfobj" }, { 72, "compat object size mismatch for copying out ipfobj" }, { 73, "error doing copyout of data for out ipfobj" }, { 74, "attempt to add existing tunable name" }, { 75, "cannot find tunable name to delete" }, { 76, "internal data too big for next tunable" }, { 77, "could not find tunable" }, { 78, "tunable can only be changed when ipfilter disabled" }, { 79, "new tunable value outside accepted range" }, { 80, "ipftune called for unrecognised ioctl" }, { 81, "" }, { 82, "could not find token to delete" }, { 83, "" }, { 84, "attempt to get next rule when no more exist" }, { 85, "value for iri_inout outside accepted range" }, { 86, "value for iri_active outside accepted range" }, { 87, "value for iri_nrules is 0" }, { 88, "NULL pointer specified for where to copy rule to" }, { 89, "copyout of rule failed" }, { 90, "" }, { 91, "could not get token for rule iteration" }, { 92, "unrecognised generic iterator" }, { 93, "could not find token for generic iterator" }, { 94, "need write permissions to disable/enable ipfilter" }, { 95, "error copying in enable/disable value" }, { 96, "need write permissions to set ipf tunable" }, { 97, "need write permissions to set ipf flags" }, { 98, "error doing copyin of ipf flags" }, { 99, "error doing copyout of ipf flags" }, { 100, "need write permissions to add another rule" }, { 101, "need write permissions to insert another rule" }, { 102, "need write permissions to swap active rule set" }, { 103, "error copying out current active rule set" }, { 104, "need write permissions to zero ipf stats" }, { 105, "need write permissions to flush ipf v4 rules" }, { 106, "error copying out v4 flush results" }, { 107, "error copying in v4 flush command" }, { 108, "need write permissions to flush ipf v6 rules" }, { 109, "error copying out v6 flush results" }, { 110, "error copying in v6 flush command" }, { 111, "error copying in new lock state for ipfilter" }, { 112, "need write permissions to flush ipf logs" }, { 113, "error copying out results of log flush" }, { 114, "need write permissions to resync ipf" }, { 115, "unrecognised ipf ioctl" }, { 116, "error copying in match array" }, { 117, "match array type is not IPFOBJ_IPFEXPR" }, { 118, "bad size for match array" }, { 119, "cannot allocate memory for match aray" }, { 120, "error copying in match array" }, { 121, "error verifying contents of match array" }, { 122, "need write permissions to set ipf lock status" }, { 123, "error copying in data for function resolution" }, { 124, "error copying in ipfobj structure" }, { 125, "error copying in ipfobj structure" }, { 126, "error copying in ipfobj structure" }, { 127, "error copying in ipfobj structure" }, { 128, "no memory for filter rule comment" }, { 129, "error copying in filter rule comment" }, { 130, "error copying out filter rule comment" }, { 131, "no memory for new rule alloc buffer" }, { 132, "cannot find source lookup pool" }, { 133, "unknown source address type" }, { 134, "cannot find destination lookup pool" }, { 135, "unknown destination address type" }, { 136, "icmp head group name index incorrect" }, { 137, "group head name index incorrect" }, { 138, "group name index incorrect" }, { 139, "to interface name index incorrect" }, { 140, "dup-to interface name index incorrect" }, { 141, "reply-to interface name index incorrect" }, { 142, "could not initialise call now function" }, { 143, "could not initialise call function" }, { 144, "could not find destination list" }, { 145, "auth rules cannot have dup/to/fastroute" }, { 146, "incorrect size for object to copy out" }, { 147, "object type out of bounds for kernel copyout" }, { 148, "object size too small for kernel copyout" }, { 149, "object size validation failed for kernel copyout" }, { 150, "error copying data out for kernel copyout" }, { 151, "version mismatch for kernel copyout" }, /* -------------------------------------------------------------------------- */ { 10001, "could not find token for auth iterator" }, { 10002, "write permissions require to add/remove auth rule" }, { 10003, "need write permissions to set auth lock" }, { 10004, "error copying out results of auth flush" }, { 10005, "unknown auth ioctl" }, { 10006, "can only append or remove preauth rules" }, { 10007, "NULL pointers passed in for preauth remove" }, { 10008, "preauth rule not found to remove" }, { 10009, "could not malloc memory for preauth entry" }, { 10010, "unrecognised preauth rule ioctl command" }, { 10011, "iterator data supplied with NULL pointer" }, { 10012, "unknown auth iterator type" }, { 10013, "iterator error copying out auth data" }, { 10014, "sleep waiting for auth packet interrupted" }, { 10015, "bad index supplied in auth reply" }, { 10016, "error injecting outbound packet back into kernel" }, { 10017, "error injecting inbound packet back into kernel" }, { 10018, "could not attempt to inject packet back into kernel" }, { 10019, "packet id does not match" }, /* -------------------------------------------------------------------------- */ { 20001, "invalid frag token data pointer supplied" }, { 20002, "error copying out frag token data" }, { 20003, "can only copy one fragment state entry at a time" }, /* -------------------------------------------------------------------------- */ { 30001, "incorrect object size to get hash table stats" }, { 30002, "could not malloc memory for new hash table" }, { 30003, "error coping in hash table structure" }, { 30004, "hash table already exists" }, { 30005, "mismach between new hash table and operation unit" }, { 30006, "could not malloc memory for hash table base" }, { 30007, "could not find hash table" }, { 30008, "mismatch between hash table and operation unit" }, { 30009, "could not find hash table for iterators next node" }, { 30010, "unknown iterator tpe" }, { 30011, "iterator error copying out hash table" }, { 30012, "iterator error copying out hash table entry" }, { 30013, "error copying out hash table statistics" }, { 30014, "table node delete structure wrong size" }, { 30015, "error copying in node to delete" }, { 30016, "table to delete node from does not exist" }, { 30017, "could not find table to remove node from" }, { 30018, "table node add structure wrong size" }, { 30019, "error copying in node to add" }, { 30020, "could not find table to add node to" }, { 30021, "node already exists in the table" }, { 30022, "could not find node to delete in table" }, { 30023, "uid mismatch on node to delete" }, { 30024, "object size incorrect for hash table" }, { 30025, "hash table size must be at least 1"}, { 30026, "cannot allocate memory for hash table context" }, /* -------------------------------------------------------------------------- */ { 40001, "invalid minor device numebr for log read" }, { 40002, "read size too small" }, { 40003, "interrupted waiting for log data to read" }, { 40004, "interrupted waiting for log data to read" }, { 40005, "read size too large" }, { 40006, "uiomove for read operation failed" }, /* -------------------------------------------------------------------------- */ { 50001, "unknown lookup ioctl" }, { 50002, "error copying in object data for add node" }, { 50003, "invalid unit for lookup add node" }, { 50004, "incorrect size for adding a pool node" }, { 50005, "error copying in pool node structure" }, { 50006, "mismatch in pool node address/mask families" }, { 50007, "could not find pool name" }, { 50008, "node already exists in pool" }, { 50009, "incorrect size for adding a hash node" }, { 50010, "error copying in hash node structure" }, { 50011, "could not find hash table name" }, { 50012, "unrecognised object type for lookup add node" }, { 50013, "invalid unit for lookup delete node" }, { 50014, "incorrect size for deleting a pool node" }, { 50015, "error copying in pool node structure" }, { 50016, "could not find pool name" }, { 50017, "could not find pool node" }, { 50018, "incorrect size for removing a hash node" }, { 50019, "error copying in hash node structure" }, { 50020, "could not find hash table name" }, { 50021, "unrecognised object type for lookup delete node" }, { 50022, "error copying in add table data" }, { 50023, "invalid unit for lookup add table" }, { 50024, "pool name already exists" }, { 50025, "hash table name already exists" }, { 50026, "unrecognised object type for lookup add table" }, { 50027, "error copying table data back out" }, { 50028, "error copying in remove table data" }, { 50029, "invalid unit for lookup remove table" }, { 50030, "unrecognised object type for lookup remove table" }, { 50031, "error copying in lookup stats structure" }, { 50032, "invalid unit for lookup stats" }, { 50033, "unrecognised object type for lookup stats" }, { 50034, "error copying in flush lookup data" }, { 50035, "invalid unit for lookup flush" }, { 50036, "incorrect table type for lookup flush" }, { 50037, "error copying out lookup flush results" }, { 50038, "invalid unit for lookup iterator" }, { 50039, "invalid unit for lookup iterator" }, { 50040, "could not find token for lookup iterator" }, { 50041, "unrecognised object type for lookup interator" }, { 50042, "error copying in lookup delete node operation" }, /* -------------------------------------------------------------------------- */ { 60001, "insufficient privilege for NAT write operation" }, { 60002, "need write permissions to flush NAT logs" }, { 60003, "need write permissions to turn NAT logging on/off" }, { 60004, "error copying out current NAT log setting" }, { 60005, "error copying out bytes waiting to be read in NAT \ log" }, { 60006, "need write permissions to add NAT rule" }, { 60007, "NAT rule already exists" }, { 60008, "could not allocate memory for NAT rule" }, { 60009, "need write permissions to remove NAT rule" }, { 60010, "NAT rule could not be found" }, { 60011, "could not find NAT entry for redirect lookup" }, { 60012, "need write permissions to flush NAT table" }, { 60013, "error copying in NAT flush command" }, { 60014, "need write permissions to do matching NAT flush" }, { 60015, "need write permissions to set NAT lock" }, { 60016, "need write permissions to add entry to NAT table" }, { 60017, "NAT not locked for size retrieval" }, { 60018, "NAT not locked for fetching NAT table entry" }, { 60019, "error copying in NAT token data for deletion" }, { 60020, "unknown NAT ioctl" }, { 60021, "" }, { 60022, "resolving proxy name in NAT rule failed" }, { 60023, "only reply age specified in NAT rule" }, { 60024, "error doing copyin to determine NAT entry size" }, { 60025, "error copying out NAT size of 0" }, { 60026, "NAT entry not found" }, { 60027, "error doing copyout of NAT entry size" }, { 60028, "invalid data size for getting NAT entry" }, { 60029, "could not malloc temporary space for NAT entry" }, { 60030, "no NAT table entries present" }, { 60031, "NAT entry to get next from not found" }, { 60032, "not enough space for proxy structure" }, { 60033, "not enough space for private proxy data" }, { 60034, "NAT entry size is too large" }, { 60035, "could not malloc memory for NAT entry sratch space" }, { 60036, "" }, { 60037, "could not malloc memory for NAT entry" }, { 60038, "could not malloc memory for NAT entry rule" }, { 60039, "could not resolve NAT entry rule's proxy" }, { 60040, "cannot add outbound duplicate NAT entry" }, { 60041, "cannot add inbound duplicate NAT entry" }, { 60042, "cannot add NAT entry that is neither IN nor OUT" }, { 60043, "could not malloc memory for NAT proxy data" }, { 60044, "proxy data size too big" }, { 60045, "could not malloc proxy private data for NAT entry" }, { 60046, "could not malloc memory for new NAT filter rule" }, { 60047, "could not find existing filter rule for NAT entry" }, { 60048, "insertion into NAT table failed" }, { 60049, "iterator error copying out hostmap data" }, { 60050, "iterator error copying out NAT rule data" }, { 60051, "iterator error copying out NAT entry data" }, { 60052, "iterator data supplied with NULL pointer" }, { 60053, "unknown NAT iterator type" }, { 60054, "unknwon next address type" }, { 60055, "iterator suppled with unknown type for get-next" }, { 60056, "unknown lookup group for next address" }, { 60057, "error copying out NAT log flush results" }, { 60058, "bucket table type is incorrect" }, { 60059, "error copying out NAT bucket table" }, { 60060, "function not found for lookup" }, { 60061, "address family not supported with SIOCSTPUT" }, { 60062, "unknown timeout name" }, { 60063, "cannot allocate new inbound NAT entry table" }, { 60064, "cannot allocate new outbound NAT entry table" }, { 60065, "cannot allocate new inbound NAT bucketlen table" }, { 60066, "cannot allocate new outbound NAT bucketlen table" }, { 60067, "cannot allocate new NAT rules table" }, { 60068, "cannot allocate new NAT hostmap table" }, { 60069, "new source lookup type is not dstlist" }, { 60070, "cannot allocate NAT rule scratch space" }, { 60071, "new destination lookup type is not dstlist" }, { 60072, "function not found for lookup (ipv6)" }, { 60073, "unknown lookup group for next address (ipv6)" }, { 60074, "unknown next address type (ipv6)" }, { 60075, "one object at a time must be copied" }, /* -------------------------------------------------------------------------- */ { 70001, "incorrect object size to get pool stats" }, { 70002, "could not malloc memory for new pool node" }, { 70003, "invalid address length for new pool node" }, { 70004, "invalid mask length for new pool node" }, { 70005, "error adding node to pool" }, { 70006, "pool already exists" }, { 70007, "could not malloc memory for new pool" }, { 70008, "could not allocate radix tree for new pool" }, { 70009, "could not find pool" }, { 70010, "unknown pool name for iteration" }, { 70011, "unknown pool iterator" }, { 70012, "error copying out pool head" }, { 70013, "error copying out pool node" }, { 70014, "add node size incorrect" }, { 70015, "error copying in pool node" }, { 70016, "" }, { 70017, "cannot find pool for node" }, { 70018, "node entry already present in pool" }, { 70019, "delete node size incorrect" }, { 70020, "error copying in node to delete" }, { 70021, "cannot find pool to delete node from" }, { 70022, "cannot find node to delete in pool" }, { 70023, "pool name already exists" }, { 70024, "uid mismatch for node removal" }, { 70025, "stats device unit is invalid" }, { 70026, "error copying out statistics" }, { 70027, "could not remove node from radix tree" }, { 70028, "incorrect address length in pool node add" }, { 70029, "incorrect mask length in pool node add" }, { 70030, "incorrect address length in pool node remove" }, { 70031, "incorrect mask length in pool node remove" }, { 70032, "cannot allocate memory for pool context" }, { 70033, "cannot allocate memory for radix tree context" }, { 70034, "adding IPv6 node with incorrect address length" }, { 70035, "IPv4 address not masked" }, { 70036, "IPv6 address not masked" }, { 70037, "removing IPv6 node with incorrect address length" }, /* -------------------------------------------------------------------------- */ { 80001, "could not find proxy" }, { 80002, "proxy does not support control operations" }, { 80003, "could not allocate data to hold proxy operation" }, { 80004, "unknown proxy ioctl" }, { 80005, "could not copyin proxy control structure" }, { 80006, "DNS proxy could not find rule to delete" }, { 80007, "DNS proxy found existing matching rule" }, { 80008, "DNS proxy could not allocate memory for new rule" }, { 80009, "DNS proxy unknown command request" }, /* -------------------------------------------------------------------------- */ { 90001, "could not malloc space for new scan structure" }, { 90002, "scan tag already exists" }, { 90003, "scan structure in use" }, { 90004, "could not find matching scan tag for filter rule" }, { 90005, "could not copyout scan statistics" }, /* -------------------------------------------------------------------------- */ { 100001, "cannot find matching state entry to remove" }, { 100002, "error copying in v4 state flush command" }, { 100003, "error copying out v4 state flush results" }, { 100004, "error copying in v6 state flush command" }, { 100005, "error copying out v6 state flush results" }, { 100006, "" }, { 100007, "" }, { 100008, "need write permissions to flush state log" }, { 100009, "erorr copyout results of flushing state log" }, { 100010, "need write permissions to turn state logging on/off" }, { 100011, "error copying in new state logging state" }, { 100012, "error copying out current state logging state" }, { 100013, "error copying out bytes waiting to be read in state \ log" }, { 100014, "need write permissions to set state lock" }, { 100015, "need write permissions to add entry to state table" }, { 100016, "state not locked for size retrieval" }, { 100017, "error copying out hash table bucket lengths" }, { 100018, "could not find token for state iterator" }, { 100019, "error copying in state token data for deletion" }, { 100020, "unknown state ioctl" }, { 100021, "no state table entries present" }, { 100022, "state entry to get next from not found" }, { 100023, "could not malloc memory for state entry" }, { 100024, "could not malloc memory for state entry rule" }, { 100025, "could not copy back state entry to user space" }, { 100026, "iterator data supplied with NULL pointer" }, { 100027, "iterator supplied with 0 item count" }, { 100028, "iterator type is incorrect" }, { 100029, "invalid state token data pointer supplied" }, { 100030, "error copying out next state entry" }, { 100031, "unrecognised table request" }, { 100032, "error copying out bucket length data" }, { 100033, "could not find existing filter rule for state entry" }, { 100034, "could not find timeout name" }, { 100035, "could not allocate new state table" }, { 100036, "could not allocate new state bucket length table" }, /* -------------------------------------------------------------------------- */ { 110001, "sync write header magic number is incorrect" }, { 110002, "sync write header protocol is incorrect" }, { 110003, "sync write header command is incorrect" }, { 110004, "sync write header table number is incorrect" }, { 110005, "data structure too small for sync write operation" }, { 110006, "zero length data with sync write header" }, { 110007, "insufficient data for sync write" }, { 110008, "bad sync read size" }, { 110009, "interrupted sync read (solaris)" }, { 110010, "interrupted sync read (hpux)" }, { 110011, "interrupted sync read (osf)" }, { 110012, "interrupted sync read" }, { 110013, "could not malloc memory for sync'd state" }, { 110014, "could not malloc memory for sync-state list item" }, { 110015, "sync update could not find state" }, { 110016, "unrecognised sync state command" }, { 110017, "could not malloc memory for new sync'd NAT entry" }, { 110018, "could not malloc memory for sync-NAT list item" }, { 110019, "sync update could not find NAT entry" }, { 110020, "unrecognised sync NAT command" }, { 110021, "ioctls are not handled with sync" }, /* -------------------------------------------------------------------------- */ { 120001, "null data pointer for iterator" }, { 120002, "unit outside of acceptable range" }, { 120003, "unknown iterator subtype" }, { 120004, "cannot find dest. list for iteration" }, { 120005, "error copying out destination iteration list" }, { 120006, "error copying out destination iteration node" }, { 120007, "wrong size for frdest_t structure" }, { 120008, "cannot allocate memory for new destination node" }, { 120009, "error copying in destination node to add" }, { 120010, "could not find destination list to add node to" }, { 120011, "error copying in destination node to remove" }, { 120012, "could not find dest. list to remove node from" }, { 120013, "destination list already exists" }, { 120014, "could not allocate new destination table" }, { 120015, "could not find destination list to remove" }, { 120016, "destination list cannot be removed - it is busy" }, { 120017, "error copying in names for destination" }, { 120018, "destination name is too long/short" }, { 120019, "unrecognised address family in destination" }, { 120020, "" }, { 120021, "error copying in new destination table" }, { 120022, "cannot allocate memory for node table" }, { 120023, "stats object size is incorrect for dest. lists" }, { 120024, "stats device unit is invalid for dest. lists" }, { 120025, "error copying out dest. list statistics" }, { 120026, "cannot allocate memory for destination node" }, { 120027, "error copying in destination node" }, { 120028, "cannot allocate memory for destination context " }, /* -------------------------------------------------------------------------- */ { 130001, "ioctl denied by system security level" }, { 130002, "ioctl operation on invalid minor device" }, { 130003, "ioctl on device denied, ipfitler is disabled" }, { 130004, "ioctl command not allowed when disabled" }, { 130005, "ioctl denied due to insufficient authorisation" }, { 130006, "cannot read while ipfilter is disabled" }, { 130007, "read on minor device not supported" }, { 130008, "cannot write while ipfilter is disabled" }, { 130009, "write on minor device not supported" }, { 130010, "poll on minor device is not supported" }, { 130011, "error removing IPv4 filter hooks" }, { 130012, "error removing IPv6 filter hooks" }, { 130013, "attaching IPv4 hook failed" }, { 130014, "attaching IPv6 hook failed" }, { 130015, "ipf_init_all failed" }, { 130016, "finding pfil head failed" }, { 130017, "ipfilter is already initialised and running" }, }; static ipf_error_entry_t * find_error(int errnum) { ipf_error_entry_t *ie; int l = -1, r = IPF_NUM_ERRORS + 1, step; step = (r - l) / 2;; while (step != 0) { ie = ipf_errors + l + step; if (ie->iee_number == errnum) - return ie; + return(ie); step = l + step; if (ie->iee_number > errnum) r = step; else l = step; step = (r - l) / 2;; } - return NULL; + return(NULL); } char * ipf_geterror(int fd, ioctlfunc_t *func) { static char text[80]; ipf_error_entry_t *ie; int errnum; if ((*func)(fd, SIOCIPFINTERROR, &errnum) == 0) { ie = find_error(errnum); if (ie != NULL) - return ie->iee_text; + return(ie->iee_text); snprintf(text, sizeof(text), "unknown error %d", errnum); } else { snprintf(text, sizeof(text), "retrieving error number failed (%d)", errno); } - return text; + return(text); } char * ipf_strerror(int errnum) { static char text[80]; ipf_error_entry_t *ie; ie = find_error(errnum); if (ie != NULL) - return ie->iee_text; + return(ie->iee_text); snprintf(text, sizeof(text), "unknown error %d", errnum); - return text; + return(text); } diff --git a/sbin/ipf/libipf/ipf_perror.c b/sbin/ipf/libipf/ipf_perror.c index 13fc5f0296e4..4c315bebe8db 100644 --- a/sbin/ipf/libipf/ipf_perror.c +++ b/sbin/ipf/libipf/ipf_perror.c @@ -1,40 +1,40 @@ #include #include #include "ipf.h" void ipf_perror(int err, char *string) { if (err == 0) fprintf(stderr, "%s\n", string); else fprintf(stderr, "%s: %s\n", string, ipf_strerror(err)); } int ipf_perror_fd( int fd, ioctlfunc_t iocfunc, char *string) { int save; int realerr; save = errno; if ((*iocfunc)(fd, SIOCIPFINTERROR, &realerr) == -1) realerr = 0; errno = save; fprintf(stderr, "%d:", realerr); ipf_perror(realerr, string); - return realerr ? realerr : save; + return(realerr ? realerr : save); } void ipferror(int fd, char *msg) { if (fd >= 0) { ipf_perror_fd(fd, ioctl, msg); } else { fprintf(stderr, "0:"); perror(msg); } } diff --git a/sbin/ipf/libipf/ipft_hx.c b/sbin/ipf/libipf/ipft_hx.c index 8b27ddd33bd6..b8b55ee8b34b 100644 --- a/sbin/ipf/libipf/ipft_hx.c +++ b/sbin/ipf/libipf/ipft_hx.c @@ -1,182 +1,182 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include "ipf.h" #include "ipt.h" extern int opts; static int hex_open(char *); static int hex_close(void); static int hex_readip(mb_t *, char **, int *); static char *readhex(char *, char *); struct ipread iphex = { hex_open, hex_close, hex_readip, 0 }; static FILE *tfp = NULL; static int tfd = -1; static int hex_open(char *fname) { if (tfp && tfd != -1) { rewind(tfp); - return tfd; + return(tfd); } if (!strcmp(fname, "-")) { tfd = 0; tfp = stdin; } else { tfd = open(fname, O_RDONLY); if (tfd != -1) tfp = fdopen(tfd, "r"); } - return tfd; + return(tfd); } static int hex_close(void) { int cfd = tfd; tfd = -1; - return close(cfd); + return(close(cfd)); } static int hex_readip(mb_t *mb, char **ifn, int *dir) { register char *s, *t, *u; char line[513]; ip_t *ip; char *buf; buf = (char *)mb->mb_buf; /* * interpret start of line as possibly "[ifname]" or * "[in/out,ifname]". */ if (ifn) *ifn = NULL; if (dir) *dir = 0; ip = (ip_t *)buf; while (fgets(line, sizeof(line)-1, tfp)) { if ((s = strchr(line, '\n'))) { if (s == line) { mb->mb_len = (char *)ip - buf; - return mb->mb_len; + return(mb->mb_len); } *s = '\0'; } if ((s = strchr(line, '#'))) *s = '\0'; if (!*line) continue; if ((opts & OPT_DEBUG) != 0) { printf("input: %s", line); } if ((*line == '[') && (s = strchr(line, ']'))) { t = line + 1; if (s - t > 0) { *s++ = '\0'; if ((u = strchr(t, ',')) && (u < s)) { u++; if (ifn) *ifn = strdup(u); if (dir) { if (*t == 'i') *dir = 0; else if (*t == 'o') *dir = 1; } } else if (ifn) *ifn = t; } while (*s++ == '+') { if (!strncasecmp(s, "mcast", 5)) { mb->mb_flags |= M_MCAST; s += 5; } if (!strncasecmp(s, "bcast", 5)) { mb->mb_flags |= M_BCAST; s += 5; } if (!strncasecmp(s, "mbcast", 6)) { mb->mb_flags |= M_MBCAST; s += 6; } } while (ISSPACE(*s)) s++; } else s = line; t = (char *)ip; ip = (ip_t *)readhex(s, (char *)ip); if ((opts & OPT_DEBUG) != 0) { if (opts & OPT_ASCII) { int c = *t; if (t < (char *)ip) putchar('\t'); while (t < (char *)ip) { if (isprint(c) && isascii(c)) putchar(c); else putchar('.'); t++; } } putchar('\n'); fflush(stdout); } } if (feof(tfp)) - return 0; - return -1; + return(0); + return(-1); } static char *readhex(register char *src, register char *dst) { int state = 0; char c; while ((c = *src++)) { if (ISSPACE(c)) { if (state) { dst++; state = 0; } continue; } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { c = ISDIGIT(c) ? (c - '0') : (TOUPPER(c) - 55); if (state == 0) { *dst = (c << 4); state++; } else { *dst++ |= c; state = 0; } } else break; } - return dst; + return(dst); } diff --git a/sbin/ipf/libipf/ipft_pc.c b/sbin/ipf/libipf/ipft_pc.c index 9fab5234d18c..b9aa8eefa10b 100644 --- a/sbin/ipf/libipf/ipft_pc.c +++ b/sbin/ipf/libipf/ipft_pc.c @@ -1,249 +1,249 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include "ipt.h" #if !defined(lint) static const char rcsid[] = "@(#)$Id$"; #endif struct llc { int lc_type; int lc_sz; /* LLC header length */ int lc_to; /* LLC Type offset */ int lc_tl; /* LLC Type length */ }; /* * While many of these maybe the same, some do have different header formats * which make this useful. */ static struct llc llcs[] = { { 0, 0, 0, 0 }, /* DLT_NULL */ { 1, 14, 12, 2 }, /* DLT_Ethernet */ { 10, 0, 0, 0 }, /* DLT_FDDI */ { 12, 0, 0, 0 }, /* DLT_RAW */ { -1, -1, -1, -1 } }; typedef struct { u_int id; u_short major; u_short minor; u_int timezone; u_int sigfigs; u_int snaplen; u_int type; } fileheader_t; typedef struct { u_32_t seconds; u_32_t microseconds; u_32_t caplen; u_32_t wirelen; } packetheader_t; static int ipcap_open(char *); static int ipcap_close(void); static int ipcap_readip(mb_t *, char **, int *); static int ipcap_read_rec(packetheader_t *); static void iswap_hdr(fileheader_t *); static int pfd = -1, swapped = 0; static struct llc *llcp = NULL; struct ipread pcap = { ipcap_open, ipcap_close, ipcap_readip, 0 }; #define SWAPLONG(y) \ ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) #define SWAPSHORT(y) \ ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) static void iswap_hdr(fileheader_t *p) { p->major = SWAPSHORT(p->major); p->minor = SWAPSHORT(p->minor); p->timezone = SWAPLONG(p->timezone); p->sigfigs = SWAPLONG(p->sigfigs); p->snaplen = SWAPLONG(p->snaplen); p->type = SWAPLONG(p->type); } static int ipcap_open(char *fname) { fileheader_t ph; int fd, i; if (pfd != -1) - return pfd; + return(pfd); if (!strcmp(fname, "-")) fd = 0; else if ((fd = open(fname, O_RDONLY)) == -1) - return -1; + return(-1); if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) - return -2; + return(-2); if (ph.id != 0xa1b2c3d4) { if (SWAPLONG(ph.id) != 0xa1b2c3d4) { (void) close(fd); - return -2; + return(-2); } swapped = 1; iswap_hdr(&ph); } for (i = 0; llcs[i].lc_type != -1; i++) if (llcs[i].lc_type == ph.type) { llcp = llcs + i; break; } if (llcp == NULL) { (void) close(fd); - return -2; + return(-2); } pfd = fd; printf("opened pcap file %s:\n", fname); printf("\tid: %08x version: %d.%d type: %d snap %d\n", ph.id, ph.major, ph.minor, ph.type, ph.snaplen); - return fd; + return(fd); } static int ipcap_close(void) { - return close(pfd); + return(close(pfd)); } /* * read in the header (and validate) which should be the first record * in a pcap file. */ static int ipcap_read_rec(packetheader_t *rec) { int n, p, i; n = sizeof(*rec); while (n > 0) { i = read(pfd, (char *)rec, sizeof(*rec)); if (i <= 0) - return -2; + return(-2); n -= i; } if (swapped) { rec->caplen = SWAPLONG(rec->caplen); rec->wirelen = SWAPLONG(rec->wirelen); rec->seconds = SWAPLONG(rec->seconds); rec->microseconds = SWAPLONG(rec->microseconds); } p = rec->caplen; n = MIN(p, rec->wirelen); if (!n || n < 0) - return -3; + return(-3); if (p < 0 || p > 65536) - return -4; - return p; + return(-4); + return(p); } #ifdef notyet /* * read an entire pcap packet record. only the data part is copied into * the available buffer, with the number of bytes copied returned. */ static int ipcap_read(char *buf, int cnt) { packetheader_t rec; static char *bufp = NULL; int i, n; if ((i = ipcap_read_rec(&rec)) <= 0) - return i; + return(i); if (!bufp) bufp = malloc(i); else bufp = realloc(bufp, i); if (read(pfd, bufp, i) != i) - return -2; + return(-2); n = MIN(i, cnt); bcopy(bufp, buf, n); - return n; + return(n); } #endif /* - * return only an IP packet read into buf +* return only an IP packet read into buf */ static int ipcap_readip(mb_t *mb, char **ifn, int *dir) { static char *bufp = NULL; packetheader_t rec; struct llc *l; char *s, ty[4]; int i, j, n; char *buf; int cnt; #if 0 ifn = ifn; /* gcc -Wextra */ dir = dir; /* gcc -Wextra */ #endif buf = (char *)mb->mb_buf; cnt = sizeof(mb->mb_buf); l = llcp; /* do { */ if ((i = ipcap_read_rec(&rec)) <= 0) - return i; + return(i); if (!bufp) bufp = malloc(i); else bufp = realloc(bufp, i); s = bufp; for (j = i, n = 0; j > 0; ) { n = read(pfd, s, j); if (n <= 0) - return -2; + return(-2); j -= n; s += n; } s = bufp; i -= l->lc_sz; s += l->lc_to; bcopy(s, ty, l->lc_tl); s += l->lc_tl; /* } while (ty[0] != 0x8 && ty[1] != 0); */ n = MIN(i, cnt); bcopy(s, buf, n); mb->mb_len = n; - return n; + return(n); } diff --git a/sbin/ipf/libipf/ipft_tx.c b/sbin/ipf/libipf/ipft_tx.c index 3b6b580c705b..e38cd94e355b 100644 --- a/sbin/ipf/libipf/ipft_tx.c +++ b/sbin/ipf/libipf/ipft_tx.c @@ -1,500 +1,500 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #if !defined(lint) static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif #include #include "ipf.h" #include "ipt.h" extern int opts; static char *tx_proto = ""; static int text_open(char *), text_close(void); static int text_readip(mb_t *, char **, int *); static int parseline(char *, ip_t *, char **, int *); static char myflagset[] = "FSRPAUEC"; static u_char myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG, TH_ECN, TH_CWR }; struct ipread iptext = { text_open, text_close, text_readip, R_DO_CKSUM }; static FILE *tfp = NULL; static int tfd = -1; static u_32_t tx_hostnum(char *, int *); static u_short tx_portnum(char *); #ifdef USE_INET6 int parseipv6(char **, ip6_t *, char **, int *); #endif /* * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */ static u_32_t tx_hostnum(char *host, int *resolved) { i6addr_t ipa; *resolved = 0; if (!strcasecmp("any", host)) - return 0L; + return(0L); if (ISDIGIT(*host)) - return inet_addr(host); + return(inet_addr(host)); if (gethost(AF_INET, host, &ipa) == -1) { *resolved = -1; fprintf(stderr, "can't resolve hostname: %s\n", host); - return 0; + return(0); } - return ipa.in4.s_addr; + return(ipa.in4.s_addr); } /* * find the port number given by the name, either from getservbyname() or * straight atoi() */ static u_short tx_portnum(char *name) { struct servent *sp; if (ISDIGIT(*name)) - return (u_short)atoi(name); + return(u_short)atoi(name); sp = getservbyname(name, tx_proto); if (sp) - return ntohs(sp->s_port); + return(ntohs(sp->s_port)); (void) fprintf(stderr, "unknown service \"%s\".\n", name); - return 0; + return(0); } static int text_open(char *fname) { if (tfp && tfd != -1) { rewind(tfp); - return tfd; + return(tfd); } if (!strcmp(fname, "-")) { tfd = 0; tfp = stdin; } else { tfd = open(fname, O_RDONLY); if (tfd != -1) tfp = fdopen(tfd, "r"); } - return tfd; + return(tfd); } static int text_close(void) { int cfd = tfd; tfd = -1; - return close(cfd); + return(close(cfd)); } static int text_readip(mb_t *mb, char **ifn, int *dir) { register char *s; char line[513]; ip_t *ip; char *buf; buf = (char *)mb->mb_buf; *ifn = NULL; while (fgets(line, sizeof(line)-1, tfp)) { if ((s = strchr(line, '\n'))) *s = '\0'; if ((s = strchr(line, '\r'))) *s = '\0'; if ((s = strchr(line, '#'))) *s = '\0'; if (!*line) continue; if ((opts & OPT_DEBUG) != 0) printf("input: %s\n", line); *ifn = NULL; *dir = 0; if (!parseline(line, (ip_t *)buf, ifn, dir)) { ip = (ip_t *)buf; if (IP_V(ip) == 6) { #ifdef USE_INET6 mb->mb_len = ntohs(((ip6_t *)ip)->ip6_plen) + sizeof(ip6_t); #else mb->mb_len = 0; #endif } else { mb->mb_len = ntohs(ip->ip_len); } - return mb->mb_len; + return(mb->mb_len); } } if (feof(tfp)) - return 0; - return -1; + return(0); + return(-1); } static int parseline(char *line, ip_t *ip, char **ifn, int *out) { tcphdr_t th, *tcp = &th; struct icmp icmp, *ic = &icmp; char *cps[20], **cpp, c, ipopts[68]; int i, r; if (*ifn) free(*ifn); bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip)); bzero((char *)tcp, sizeof(*tcp)); bzero((char *)ic, sizeof(*ic)); bzero(ipopts, sizeof(ipopts)); IP_HL_A(ip, sizeof(*ip) >> 2); IP_V_A(ip, IPVERSION); ip->ip_ttl = 63; for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; ) cps[++i] = strtok(NULL, " \b\t\r\n"); cpp = cps; if (!*cpp) - return 1; + return(1); c = **cpp; if (!ISALPHA(c) || (TOLOWER(c) != 'o' && TOLOWER(c) != 'i')) { fprintf(stderr, "bad direction \"%s\"\n", *cpp); - return 1; + return(1); } #ifdef USE_INET6 if (!strcasecmp(*cpp, "out6") || !strcasecmp(*cpp, "in6")) { - return parseipv6(cpp, (ip6_t *)ip, ifn, out); + return(parseipv6(cpp, (ip6_t *)ip, ifn, out)); } #endif *out = (TOLOWER(c) == 'o') ? 1 : 0; cpp++; if (!*cpp) - return 1; + return(1); if (!strcasecmp(*cpp, "on")) { cpp++; if (!*cpp) - return 1; + return(1); *ifn = strdup(*cpp++); if (!*cpp) - return 1; + return(1); } c = **cpp; ip->ip_len = sizeof(ip_t); if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") || !strcasecmp(*cpp, "icmp")) { if (c == 't') { ip->ip_p = IPPROTO_TCP; ip->ip_len += sizeof(struct tcphdr); tx_proto = "tcp"; } else if (c == 'u') { ip->ip_p = IPPROTO_UDP; ip->ip_len += sizeof(struct udphdr); tx_proto = "udp"; } else { ip->ip_p = IPPROTO_ICMP; ip->ip_len += ICMPERR_IPICMPHLEN; tx_proto = "icmp"; } cpp++; } else if (ISDIGIT(**cpp) && !index(*cpp, '.')) { ip->ip_p = atoi(*cpp); cpp++; } else ip->ip_p = IPPROTO_IP; if (!*cpp) - return 1; + return(1); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { char *last; last = strchr(*cpp, ','); if (!last) { fprintf(stderr, "tcp/udp with no source port\n"); - return 1; + return(1); } *last++ = '\0'; tcp->th_sport = htons(tx_portnum(last)); if (ip->ip_p == IPPROTO_TCP) { tcp->th_win = htons(4096); TCP_OFF_A(tcp, sizeof(*tcp) >> 2); } } ip->ip_src.s_addr = tx_hostnum(*cpp, &r); cpp++; if (!*cpp) - return 1; + return(1); if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { char *last; last = strchr(*cpp, ','); if (!last) { fprintf(stderr, "tcp/udp with no destination port\n"); - return 1; + return(1); } *last++ = '\0'; tcp->th_dport = htons(tx_portnum(last)); } ip->ip_dst.s_addr = tx_hostnum(*cpp, &r); cpp++; if (ip->ip_p == IPPROTO_TCP) { if (*cpp != NULL) { char *s, *t; tcp->th_flags = 0; for (s = *cpp; *s; s++) if ((t = strchr(myflagset, *s))) tcp->th_flags |= myflags[t-myflagset]; if (tcp->th_flags) cpp++; } if (tcp->th_flags & TH_URG) tcp->th_urp = htons(1); if (*cpp && !strncasecmp(*cpp, "seq=", 4)) { tcp->th_seq = htonl(atoi(*cpp + 4)); cpp++; } if (*cpp && !strncasecmp(*cpp, "ack=", 4)) { tcp->th_ack = htonl(atoi(*cpp + 4)); cpp++; } } else if (*cpp && ip->ip_p == IPPROTO_ICMP) { char *t; t = strchr(*cpp, ','); if (t != NULL) *t = '\0'; ic->icmp_type = geticmptype(AF_INET, *cpp); if (t != NULL) ic->icmp_code = atoi(t + 1); cpp++; if (ic->icmp_type == ICMP_ECHO || ic->icmp_type == ICMP_ECHOREPLY) ic->icmp_id = htons(getpid()); if (t != NULL) *t = ','; } if (*cpp && !strcasecmp(*cpp, "opt")) { u_long olen; cpp++; olen = buildopts(*cpp, ipopts, (IP_HL(ip) - 5) << 2); if (olen) { bcopy(ipopts, (char *)(ip + 1), olen); IP_HL_A(ip, IP_HL(ip) + (olen >> 2)); ip->ip_len += olen; } } if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) bcopy((char *)tcp, ((char *)ip) + (IP_HL(ip) << 2), sizeof(*tcp)); else if (ip->ip_p == IPPROTO_ICMP) bcopy((char *)ic, ((char *)ip) + (IP_HL(ip) << 2), sizeof(*ic)); ip->ip_len = htons(ip->ip_len); - return 0; + return(0); } #ifdef USE_INET6 int parseipv6(char **cpp, ip6_t *ip6, char **ifn, int *out) { tcphdr_t th, *tcp = &th; struct icmp6_hdr icmp, *ic6 = &icmp; bzero((char *)ip6, MAX(sizeof(*tcp), sizeof(*ic6)) + sizeof(*ip6)); bzero((char *)tcp, sizeof(*tcp)); bzero((char *)ic6, sizeof(*ic6)); ip6->ip6_vfc = 0x60; *out = (**cpp == 'o') ? 1 : 0; cpp++; if (!*cpp) - return 1; + return(1); if (!strcasecmp(*cpp, "on")) { cpp++; if (!*cpp) - return 1; + return(1); *ifn = strdup(*cpp++); if (!*cpp) - return 1; + return(1); } if (!strcasecmp(*cpp, "tcp")) { ip6->ip6_nxt = IPPROTO_TCP; tx_proto = "tcp"; cpp++; } else if (!strcasecmp(*cpp, "udp")) { ip6->ip6_nxt = IPPROTO_UDP; tx_proto = "udp"; cpp++; } else if (!strcasecmp(*cpp, "icmpv6")) { ip6->ip6_nxt = IPPROTO_ICMPV6; tx_proto = "icmpv6"; cpp++; } else if (ISDIGIT(**cpp) && !index(*cpp, ':')) { ip6->ip6_nxt = atoi(*cpp); cpp++; } else ip6->ip6_nxt = IPPROTO_IPV6; if (!*cpp) - return 1; + return(1); switch (ip6->ip6_nxt) { case IPPROTO_TCP : ip6->ip6_plen = sizeof(struct tcphdr); break; case IPPROTO_UDP : ip6->ip6_plen = sizeof(struct udphdr); break; case IPPROTO_ICMPV6 : ip6->ip6_plen = ICMP6ERR_IPICMPHLEN; break; default : break; } if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { char *last; last = strchr(*cpp, ','); if (!last) { fprintf(stderr, "tcp/udp with no source port\n"); - return 1; + return(1); } *last++ = '\0'; tcp->th_sport = htons(tx_portnum(last)); if (ip6->ip6_nxt == IPPROTO_TCP) { tcp->th_win = htons(4096); TCP_OFF_A(tcp, sizeof(*tcp) >> 2); } } if (inet_pton(AF_INET6, *cpp, &ip6->ip6_src) != 1) { fprintf(stderr, "cannot parse source address '%s'\n", *cpp); - return 1; + return(1); } cpp++; if (!*cpp) - return 1; + return(1); if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { char *last; last = strchr(*cpp, ','); if (!last) { fprintf(stderr, "tcp/udp with no destination port\n"); - return 1; + return(1); } *last++ = '\0'; tcp->th_dport = htons(tx_portnum(last)); } if (inet_pton(AF_INET6, *cpp, &ip6->ip6_dst) != 1) { fprintf(stderr, "cannot parse destination address '%s'\n", *cpp); - return 1; + return(1); } cpp++; if (ip6->ip6_nxt == IPPROTO_TCP) { if (*cpp != NULL) { char *s, *t; tcp->th_flags = 0; for (s = *cpp; *s; s++) if ((t = strchr(myflagset, *s))) tcp->th_flags |= myflags[t-myflagset]; if (tcp->th_flags) cpp++; } if (tcp->th_flags & TH_URG) tcp->th_urp = htons(1); if (*cpp && !strncasecmp(*cpp, "seq=", 4)) { tcp->th_seq = htonl(atoi(*cpp + 4)); cpp++; } if (*cpp && !strncasecmp(*cpp, "ack=", 4)) { tcp->th_ack = htonl(atoi(*cpp + 4)); cpp++; } } else if (*cpp && ip6->ip6_nxt == IPPROTO_ICMPV6) { char *t; t = strchr(*cpp, ','); if (t != NULL) *t = '\0'; ic6->icmp6_type = geticmptype(AF_INET6, *cpp); if (t != NULL) ic6->icmp6_code = atoi(t + 1); if (ic6->icmp6_type == ICMP6_ECHO_REQUEST || ic6->icmp6_type == ICMP6_ECHO_REPLY) ic6->icmp6_id = htons(getpid()); if (t != NULL) *t = ','; } if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { bcopy((char *)tcp, (char *)ip6 + sizeof(*ip6), sizeof(*tcp)); } else if (ip6->ip6_nxt == IPPROTO_ICMPV6) { bcopy((char *)ic6, (char *)ip6 + sizeof(*ip6), sizeof(*ic6)); } /* * Because a length of 0 == jumbo gram... */ if (ip6->ip6_plen == 0) { ip6->ip6_plen++; } ip6->ip6_plen = htons(ip6->ip6_plen); - return 0; + return(0); } #endif diff --git a/sbin/ipf/libipf/ipoptsec.c b/sbin/ipf/libipf/ipoptsec.c index e6c8f042748c..bcfb2ed4a3bd 100644 --- a/sbin/ipf/libipf/ipoptsec.c +++ b/sbin/ipf/libipf/ipoptsec.c @@ -1,61 +1,61 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" struct ipopt_names secclass[] = { { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" }, { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" }, { IPSO_CLASS_SECR, 0x04, 0, "secret" }, { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" }, { IPSO_CLASS_CONF, 0x10, 0, "confid" }, { IPSO_CLASS_UNCL, 0x20, 0, "unclass" }, { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" }, { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" }, { 0, 0, 0, NULL } /* must be last */ }; u_char seclevel(char *slevel) { struct ipopt_names *so; if (slevel == NULL || *slevel == '\0') - return 0; + return(0); for (so = secclass; so->on_name; so++) if (!strcasecmp(slevel, so->on_name)) break; if (!so->on_name) { fprintf(stderr, "no such security level: '%s'\n", slevel); - return 0; + return(0); } - return (u_char)so->on_value; + return(u_char)so->on_value; } u_char secbit(int class) { struct ipopt_names *so; for (so = secclass; so->on_name; so++) if (so->on_value == class) break; if (!so->on_name) { fprintf(stderr, "no such security class: %d.\n", class); - return 0; + return(0); } - return (u_char)so->on_bit; + return(u_char)so->on_bit; } diff --git a/sbin/ipf/libipf/kmem.c b/sbin/ipf/libipf/kmem.c index 635f84507d1a..5665539089a6 100644 --- a/sbin/ipf/libipf/kmem.c +++ b/sbin/ipf/libipf/kmem.c @@ -1,114 +1,114 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ /* * kmemcpy() - copies n bytes from kernel memory into user buffer. * returns 0 on success, -1 on error. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kmem.h" #if !defined(lint) static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed"; static const char rcsid[] = "@(#)$Id$"; #endif static kvm_t *kvm_f = NULL; int openkmem(char *kern, char *core) { kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); if (kvm_f == NULL) { perror("openkmem:open"); - return -1; + return(-1); } - return kvm_f != NULL; + return(kvm_f != NULL); } int kmemcpy(register char *buf, long pos, register int n) { register int r; if (!n) - return 0; + return(0); if (kvm_f == NULL) if (openkmem(NULL, NULL) == -1) - return -1; + return(-1); while ((r = kvm_read(kvm_f, pos, buf, n)) < n) if (r <= 0) { fprintf(stderr, "pos=0x%lx ", (u_long)pos); perror("kmemcpy:read"); - return -1; + return(-1); } else { buf += r; pos += r; n -= r; } - return 0; + return(0); } int kstrncpy(register char *buf, long pos, register int n) { register int r; if (!n) - return 0; + return(0); if (kvm_f == NULL) if (openkmem(NULL, NULL) == -1) - return -1; + return(-1); while (n > 0) { r = kvm_read(kvm_f, pos, buf, 1); if (r <= 0) { fprintf(stderr, "pos=0x%lx ", (u_long)pos); perror("kmemcpy:read"); - return -1; + return(-1); } else { if (*buf == '\0') break; buf++; pos++; n--; } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/kmemcpywrap.c b/sbin/ipf/libipf/kmemcpywrap.c index c5c5739a33ba..602f7a420ad6 100644 --- a/sbin/ipf/libipf/kmemcpywrap.c +++ b/sbin/ipf/libipf/kmemcpywrap.c @@ -1,22 +1,22 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include "kmem.h" int kmemcpywrap(void *from, void *to, size_t size) { int ret; ret = kmemcpy((caddr_t)to, (u_long)from, size); - return ret; + return(ret); } diff --git a/sbin/ipf/libipf/kvatoname.c b/sbin/ipf/libipf/kvatoname.c index bc59960a51b0..78af05abef12 100644 --- a/sbin/ipf/libipf/kvatoname.c +++ b/sbin/ipf/libipf/kvatoname.c @@ -1,38 +1,38 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include #include char * kvatoname(ipfunc_t func, ioctlfunc_t iocfunc) { static char funcname[40]; ipfunc_resolve_t res; int fd; res.ipfu_addr = func; res.ipfu_name[0] = '\0'; fd = -1; if ((opts & OPT_DONTOPEN) == 0) { fd = open(IPL_NAME, O_RDONLY); if (fd == -1) - return NULL; + return(NULL); } (void) (*iocfunc)(fd, SIOCFUNCL, &res); if (fd >= 0) close(fd); strncpy(funcname, res.ipfu_name, sizeof(funcname)); funcname[sizeof(funcname) - 1] = '\0'; - return funcname; + return(funcname); } diff --git a/sbin/ipf/libipf/load_dstlist.c b/sbin/ipf/libipf/load_dstlist.c index 484968532a3c..116afb33fbf7 100644 --- a/sbin/ipf/libipf/load_dstlist.c +++ b/sbin/ipf/libipf/load_dstlist.c @@ -1,66 +1,66 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_dstlist.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_dstlist.h" int load_dstlist(ippool_dst_t *dst, ioctlfunc_t iocfunc, ipf_dstnode_t *nodes) { iplookupop_t op; ipf_dstnode_t *a; ippool_dst_t dest; if (dst->ipld_name[0] == '\0') - return -1; + return(-1); if (pool_open() == -1) - return -1; + return(-1); op.iplo_unit = dst->ipld_unit; op.iplo_type = IPLT_DSTLIST; op.iplo_arg = 0; strncpy(op.iplo_name, dst->ipld_name, sizeof(op.iplo_name)); op.iplo_size = sizeof(dest); op.iplo_struct = &dest; bzero((char *)&dest, sizeof(dest)); dest.ipld_unit = dst->ipld_unit; dest.ipld_policy = dst->ipld_policy; dest.ipld_flags = dst->ipld_flags; strncpy(dest.ipld_name, dst->ipld_name, sizeof(dest.ipld_name)); if ((opts & OPT_REMOVE) == 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "add destination list table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "add destination list table")); } } if ((opts & OPT_VERBOSE) != 0) { dest.ipld_dests = dst->ipld_dests; printdstlist(&dest, bcopywrap, dest.ipld_name, opts, nodes, NULL); dest.ipld_dests = NULL; } for (a = nodes; a != NULL; a = a->ipfd_next) load_dstlistnode(dst->ipld_unit, dest.ipld_name, a, iocfunc); if ((opts & OPT_REMOVE) != 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "delete destination list table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "delete destination list table")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_dstlistnode.c b/sbin/ipf/libipf/load_dstlistnode.c index a09c7a614468..98b19882bc12 100644 --- a/sbin/ipf/libipf/load_dstlistnode.c +++ b/sbin/ipf/libipf/load_dstlistnode.c @@ -1,67 +1,67 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_dstlistnode.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" int load_dstlistnode(int role, char *name, ipf_dstnode_t *node, ioctlfunc_t iocfunc) { iplookupop_t op; frdest_t *dst; char *what; int err; if (pool_open() == -1) - return -1; + return(-1); dst = calloc(1, sizeof(*dst) + node->ipfd_dest.fd_name); if (dst == NULL) - return -1; + return(-1); op.iplo_unit = role; op.iplo_type = IPLT_DSTLIST; op.iplo_arg = 0; op.iplo_struct = dst; op.iplo_size = sizeof(*dst); if (node->ipfd_dest.fd_name >= 0) op.iplo_size += node->ipfd_dest.fd_name; (void) strncpy(op.iplo_name, name, sizeof(op.iplo_name)); dst->fd_addr = node->ipfd_dest.fd_addr; dst->fd_type = node->ipfd_dest.fd_type; dst->fd_name = node->ipfd_dest.fd_name; if (node->ipfd_dest.fd_name >= 0) bcopy(node->ipfd_names, (char *)dst + sizeof(*dst), node->ipfd_dest.fd_name); if ((opts & OPT_REMOVE) == 0) { what = "add"; err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); } else { what = "delete"; err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); } free(dst); if (err != 0) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; (void) snprintf(msg, sizeof(msg), "%s lookup node", what); - return ipf_perror_fd(pool_fd(), iocfunc, msg); + return(ipf_perror_fd(pool_fd(), iocfunc, msg)); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_file.c b/sbin/ipf/libipf/load_file.c index a1d1f70b5c33..eb3cc79e2b12 100644 --- a/sbin/ipf/libipf/load_file.c +++ b/sbin/ipf/libipf/load_file.c @@ -1,96 +1,96 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_file.c,v 1.6.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" #include alist_t * load_file(char *filename) { alist_t *a, *rtop, *rbot; char *s, line[1024], *t; int linenum, not; FILE *fp; fp = fopen(filename + 7, "r"); if (fp == NULL) { fprintf(stderr, "load_file cannot open '%s'\n", filename); - return NULL; + return(NULL); } a = NULL; rtop = NULL; rbot = NULL; linenum = 0; while (fgets(line, sizeof(line) - 1, fp)) { line[sizeof(line) - 1] = '\0'; linenum++; /* * Hunt for CR/LF. If no LF, stop processing. */ s = strchr(line, '\n'); if (s == NULL) { fprintf(stderr, "%d:%s: line too long\n", linenum, filename); fclose(fp); alist_free(rtop); - return NULL; + return(NULL); } /* * Remove trailing spaces */ for (; ISSPACE(*s); s--) *s = '\0'; s = strchr(line, '\r'); if (s != NULL) *s = '\0'; for (t = line; ISSPACE(*t); t++) ; if (*t == '!') { not = 1; t++; } else not = 0; /* * Remove comment markers */ s = strchr(t, '#'); if (s != NULL) { *s = '\0'; if (s == t) continue; } /* * Trim off tailing white spaces */ s = strlen(t) + t - 1; while (ISSPACE(*s)) *s-- = '\0'; a = alist_new(AF_UNSPEC, t); if (a != NULL) { a->al_not = not; if (rbot != NULL) rbot->al_next = a; else rtop = a; rbot = a; } else { fprintf(stderr, "%s:%d unrecognised content :%s\n", filename, linenum, t); } } fclose(fp); - return rtop; + return(rtop); } diff --git a/sbin/ipf/libipf/load_hash.c b/sbin/ipf/libipf/load_hash.c index 390195c02d72..e4561f48bb75 100644 --- a/sbin/ipf/libipf/load_hash.c +++ b/sbin/ipf/libipf/load_hash.c @@ -1,100 +1,100 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" int load_hash(iphtable_t *iphp, iphtent_t *list, ioctlfunc_t iocfunc) { iplookupop_t op; iphtable_t iph; iphtent_t *a; size_t size; int n; if (pool_open() == -1) - return -1; + return(-1); for (n = 0, a = list; a != NULL; a = a->ipe_next) n++; bzero((char *)&iph, sizeof(iph)); op.iplo_arg = 0; op.iplo_type = IPLT_HASH; op.iplo_unit = iphp->iph_unit; strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name)); if (*op.iplo_name == '\0') op.iplo_arg = IPHASH_ANON; op.iplo_size = sizeof(iph); op.iplo_struct = &iph; iph = *iphp; if (n <= 0) n = 1; if (iphp->iph_size == 0) size = n * 2 - 1; else size = iphp->iph_size; if ((list == NULL) && (size == 1)) { fprintf(stderr, "WARNING: empty hash table %s, recommend setting %s\n", iphp->iph_name, "size to match expected use"); } iph.iph_size = size; iph.iph_table = NULL; iph.iph_list = NULL; iph.iph_ref = 0; if ((opts & OPT_REMOVE) == 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "add lookup hash table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "add lookup hash table")); } } strncpy(iph.iph_name, op.iplo_name, sizeof(op.iplo_name)); strncpy(iphp->iph_name, op.iplo_name, sizeof(op.iplo_name)); if (opts & OPT_VERBOSE) { iph.iph_table = calloc(size, sizeof(*iph.iph_table)); if (iph.iph_table == NULL) { perror("calloc(size, sizeof(*iph.iph_table))"); - return -1; + return(-1); } iph.iph_list = list; printhash(&iph, bcopywrap, iph.iph_name, opts, NULL); free(iph.iph_table); for (a = list; a != NULL; a = a->ipe_next) { a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr); a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr); } } if (opts & OPT_DEBUG) printf("Hash %s:\n", iph.iph_name); for (a = list; a != NULL; a = a->ipe_next) load_hashnode(iphp->iph_unit, iph.iph_name, a, 0, iocfunc); if ((opts & OPT_REMOVE) != 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "delete lookup hash table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup hash table")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_hashnode.c b/sbin/ipf/libipf/load_hashnode.c index 2ccd8a181ac8..b0abdbd5e583 100644 --- a/sbin/ipf/libipf/load_hashnode.c +++ b/sbin/ipf/libipf/load_hashnode.c @@ -1,63 +1,63 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" int load_hashnode(int unit, char *name, iphtent_t *node, int ttl, ioctlfunc_t iocfunc) { iplookupop_t op; iphtent_t ipe; char *what; int err; if (pool_open() == -1) - return -1; + return(-1); op.iplo_type = IPLT_HASH; op.iplo_unit = unit; op.iplo_arg = 0; op.iplo_size = sizeof(ipe); op.iplo_struct = &ipe; strncpy(op.iplo_name, name, sizeof(op.iplo_name)); bzero((char *)&ipe, sizeof(ipe)); ipe.ipe_family = node->ipe_family; ipe.ipe_die = ttl; bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr, sizeof(ipe.ipe_addr)); bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask, sizeof(ipe.ipe_mask)); bcopy((char *)&node->ipe_group, (char *)&ipe.ipe_group, sizeof(ipe.ipe_group)); if ((opts & OPT_REMOVE) == 0) { what = "add"; err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); } else { what = "delete"; err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); } if (err != 0) if (!(opts & OPT_DONOTHING)) { char msg[80]; snprintf(msg, sizeof(msg), "%s node from lookup hash table", what); - return ipf_perror_fd(pool_fd(), iocfunc, msg); + return(ipf_perror_fd(pool_fd(), iocfunc, msg)); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_http.c b/sbin/ipf/libipf/load_http.c index 88fc1e37cb53..a2c2a3460fe1 100644 --- a/sbin/ipf/libipf/load_http.c +++ b/sbin/ipf/libipf/load_http.c @@ -1,208 +1,208 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_http.c,v 1.5.2.5 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" #include /* * Because the URL can be included twice into the buffer, once as the * full path for the "GET" and once as the "Host:", the buffer it is * put in needs to be larger than 512*2 to make room for the supporting * text. Why not just use snprintf and truncate? The warning about the * URL being too long tells you something is wrong and does not fetch * any data - just truncating the URL (with snprintf, etc) and sending * that to the server is allowing an unknown and unintentioned action * to happen. */ #define MAX_URL_LEN 512 #define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128) /* * Format expected is one addres per line, at the start of each line. */ alist_t * load_http(char *url) { int fd, len, left, port, endhdr, removed, linenum = 0; char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl; alist_t *a, *rtop, *rbot; size_t avail; int error; /* * More than this would just be absurd. */ if (strlen(url) > MAX_URL_LEN) { fprintf(stderr, "load_http has a URL > %d bytes?!\n", MAX_URL_LEN); - return NULL; + return(NULL); } fd = -1; rtop = NULL; rbot = NULL; avail = sizeof(buffer); error = snprintf(buffer, avail, "GET %s HTTP/1.0\r\n", url); /* * error is always less then avail due to the constraint on * the url length above. */ avail -= error; myurl = strdup(url); if (myurl == NULL) goto done; s = myurl + 7; /* http:// */ t = strchr(s, '/'); if (t == NULL) { fprintf(stderr, "load_http has a malformed URL '%s'\n", url); free(myurl); - return NULL; + return(NULL); } *t++ = '\0'; /* * 10 is the length of 'Host: \r\n\r\n' below. */ if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) { fprintf(stderr, "load_http has a malformed URL '%s'\n", url); free(myurl); - return NULL; + return(NULL); } u = strchr(s, '@'); if (u != NULL) s = u + 1; /* AUTH */ error = snprintf(buffer + strlen(buffer), avail, "Host: %s\r\n\r\n", s); if (error >= avail) { fprintf(stderr, "URL is too large: %s\n", url); goto done; } u = strchr(s, ':'); if (u != NULL) { *u++ = '\0'; port = atoi(u); if (port < 0 || port > 65535) goto done; } else { port = 80; } fd = connecttcp(s, port); if (fd == -1) goto done; len = strlen(buffer); if (write(fd, buffer, len) != len) goto done; s = buffer; endhdr = 0; left = sizeof(buffer) - 1; while ((len = read(fd, s, left)) > 0) { s[len] = '\0'; left -= len; s += len; if (endhdr >= 0) { if (endhdr == 0) { t = strchr(buffer, ' '); if (t == NULL) continue; t++; if (*t != '2') break; } u = buffer; while ((t = strchr(u, '\r')) != NULL) { if (t == u) { if (*(t + 1) == '\n') { u = t + 2; endhdr = -1; break; } else t++; } else if (*(t + 1) == '\n') { endhdr++; u = t + 2; } else u = t + 1; } if (endhdr >= 0) continue; removed = (u - buffer) + 1; memmove(buffer, u, (sizeof(buffer) - left) - removed); s -= removed; left += removed; } do { t = strchr(buffer, '\n'); if (t == NULL) break; linenum++; *t = '\0'; /* * Remove comment and continue to the next line if * the comment is at the start of the line. */ u = strchr(buffer, '#'); if (u != NULL) { *u = '\0'; if (u == buffer) continue; } /* * Trim off tailing white spaces, will include \r */ for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--) *u = '\0'; a = alist_new(AF_UNSPEC, buffer); if (a != NULL) { if (rbot != NULL) rbot->al_next = a; else rtop = a; rbot = a; } else { fprintf(stderr, "%s:%d unrecognised content:%s\n", url, linenum, buffer); } t++; removed = t - buffer; memmove(buffer, t, sizeof(buffer) - left - removed); s -= removed; left += removed; } while (1); } done: if (myurl != NULL) free(myurl); if (fd != -1) close(fd); - return rtop; + return(rtop); } diff --git a/sbin/ipf/libipf/load_pool.c b/sbin/ipf/libipf/load_pool.c index 74048388c21a..9770fedec767 100644 --- a/sbin/ipf/libipf/load_pool.c +++ b/sbin/ipf/libipf/load_pool.c @@ -1,70 +1,70 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" int load_pool(ip_pool_t *plp, ioctlfunc_t iocfunc) { iplookupop_t op; ip_pool_node_t *a; ip_pool_t pool; if (pool_open() == -1) - return -1; + return(-1); op.iplo_unit = plp->ipo_unit; op.iplo_type = IPLT_POOL; op.iplo_arg = 0; strncpy(op.iplo_name, plp->ipo_name, sizeof(op.iplo_name)); op.iplo_size = sizeof(pool); op.iplo_struct = &pool; bzero((char *)&pool, sizeof(pool)); pool.ipo_unit = plp->ipo_unit; strncpy(pool.ipo_name, plp->ipo_name, sizeof(pool.ipo_name)); if (plp->ipo_name[0] == '\0') op.iplo_arg |= IPOOL_ANON; if ((opts & OPT_REMOVE) == 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "add lookup table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "add lookup table")); } } } if (op.iplo_arg & IPOOL_ANON) strncpy(pool.ipo_name, op.iplo_name, sizeof(pool.ipo_name)); if ((opts & OPT_VERBOSE) != 0) { pool.ipo_list = plp->ipo_list; (void) printpool(&pool, bcopywrap, pool.ipo_name, opts, NULL); pool.ipo_list = NULL; } for (a = plp->ipo_list; a != NULL; a = a->ipn_next) load_poolnode(plp->ipo_unit, pool.ipo_name, a, 0, iocfunc); if ((opts & OPT_REMOVE) != 0) { if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "delete lookup table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup table")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_poolnode.c b/sbin/ipf/libipf/load_poolnode.c index d72321d06b6c..bd3c9a4a92bc 100644 --- a/sbin/ipf/libipf/load_poolnode.c +++ b/sbin/ipf/libipf/load_poolnode.c @@ -1,66 +1,66 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" int load_poolnode(int role, char *name, ip_pool_node_t *node, int ttl, ioctlfunc_t iocfunc) { ip_pool_node_t pn; iplookupop_t op; char *what; int err; if (pool_open() == -1) - return -1; + return(-1); op.iplo_unit = role; op.iplo_type = IPLT_POOL; op.iplo_arg = 0; op.iplo_struct = &pn; op.iplo_size = sizeof(pn); strncpy(op.iplo_name, name, sizeof(op.iplo_name)); bzero((char *)&pn, sizeof(pn)); bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr, sizeof(pn.ipn_addr)); bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask, sizeof(pn.ipn_mask)); pn.ipn_info = node->ipn_info; pn.ipn_die = ttl; strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); if ((opts & OPT_REMOVE) == 0) { what = "add"; err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); } else { what = "delete"; err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); } if (err != 0) { if ((opts & OPT_DONOTHING) == 0) { char msg[80]; snprintf(msg, sizeof(msg), "%s pool node(%s/", what, inet_ntoa(pn.ipn_addr.adf_addr.in4)); strcat(msg, inet_ntoa(pn.ipn_mask.adf_addr.in4)); - return ipf_perror_fd(pool_fd(), iocfunc, msg); + return(ipf_perror_fd(pool_fd(), iocfunc, msg)); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/load_url.c b/sbin/ipf/libipf/load_url.c index dcda4c07fdf8..c9b3fbe67999 100644 --- a/sbin/ipf/libipf/load_url.c +++ b/sbin/ipf/libipf/load_url.c @@ -1,31 +1,31 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: load_url.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" alist_t * load_url(char *url) { alist_t *hosts = NULL; if (strncmp(url, "file://", 7) == 0) { /* * file:///etc/passwd * ^------------s */ hosts = load_file(url); } else if (*url == '/' || *url == '.') { hosts = load_file(url); } else if (strncmp(url, "http://", 7) == 0) { hosts = load_http(url); } - return hosts; + return(hosts); } diff --git a/sbin/ipf/libipf/msgdsize.c b/sbin/ipf/libipf/msgdsize.c index e0e57ce5e8e3..c0a785ba516c 100644 --- a/sbin/ipf/libipf/msgdsize.c +++ b/sbin/ipf/libipf/msgdsize.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: msgdsize.c,v 1.2.4.3 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" size_t msgdsize(mb_t *orig) { size_t sz = 0; mb_t *m; for (m = orig; m != NULL; m = m->mb_next) sz += m->mb_len; - return sz; + return(sz); } diff --git a/sbin/ipf/libipf/nametokva.c b/sbin/ipf/libipf/nametokva.c index c1467e21eac2..b9491567d56d 100644 --- a/sbin/ipf/libipf/nametokva.c +++ b/sbin/ipf/libipf/nametokva.c @@ -1,37 +1,37 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" #include #include ipfunc_t nametokva(char *name, ioctlfunc_t iocfunc) { ipfunc_resolve_t res; int fd; strncpy(res.ipfu_name, name, sizeof(res.ipfu_name)); res.ipfu_addr = NULL; fd = -1; if ((opts & OPT_DONTOPEN) == 0) { fd = open(IPL_NAME, O_RDONLY); if (fd == -1) - return NULL; + return(NULL); } (void) (*iocfunc)(fd, SIOCFUNCL, &res); if (fd >= 0) close(fd); if (res.ipfu_addr == NULL) res.ipfu_addr = (ipfunc_t)-1; - return res.ipfu_addr; + return(res.ipfu_addr); } diff --git a/sbin/ipf/libipf/ntomask.c b/sbin/ipf/libipf/ntomask.c index 0f0887fe1f7f..3c596f43aedc 100644 --- a/sbin/ipf/libipf/ntomask.c +++ b/sbin/ipf/libipf/ntomask.c @@ -1,46 +1,46 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" int ntomask(int family, int nbits, u_32_t *ap) { u_32_t mask; if (nbits < 0) - return -1; + return(-1); switch (family) { case AF_INET : if (nbits > 32 || use_inet6 == 1) - return -1; + return(-1); if (nbits == 0) { mask = 0; } else { mask = 0xffffffff; mask <<= (32 - nbits); } *ap = htonl(mask); break; case 0 : case AF_INET6 : if ((nbits > 128) || (use_inet6 == -1)) - return -1; + return(-1); fill6bits(nbits, ap); break; default : - return -1; + return(-1); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/optname.c b/sbin/ipf/libipf/optname.c index adf12e9c5fc3..3dc4153c9761 100644 --- a/sbin/ipf/libipf/optname.c +++ b/sbin/ipf/libipf/optname.c @@ -1,63 +1,63 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" u_32_t optname(char ***cp, u_short *sp, int linenum) { struct ipopt_names *io, *so; u_long msk = 0; u_short smsk = 0; char *s; int sec = 0; for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { for (io = ionames; io->on_name; io++) if (!strcasecmp(s, io->on_name)) { msk |= io->on_bit; break; } if (!io->on_name) { fprintf(stderr, "%d: unknown IP option name %s\n", linenum, s); - return 0; + return(0); } if (!strcasecmp(s, "sec-class")) sec = 1; } if (sec && !*(*cp + 1)) { fprintf(stderr, "%d: missing security level after sec-class\n", linenum); - return 0; + return(0); } if (sec) { (*cp)++; for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { for (so = secclass; so->on_name; so++) if (!strcasecmp(s, so->on_name)) { smsk |= so->on_bit; break; } if (!so->on_name) { fprintf(stderr, "%d: no such security level: %s\n", linenum, s); - return 0; + return(0); } } if (smsk) *sp = smsk; } - return msk; + return(msk); } diff --git a/sbin/ipf/libipf/optvalue.c b/sbin/ipf/libipf/optvalue.c index 896d5fb7185f..41dee0a43759 100644 --- a/sbin/ipf/libipf/optvalue.c +++ b/sbin/ipf/libipf/optvalue.c @@ -1,34 +1,34 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" u_32_t getoptbyname(char *optname) { struct ipopt_names *io; for (io = ionames; io->on_name; io++) if (!strcasecmp(optname, io->on_name)) - return io->on_bit; - return -1; + return(io->on_bit); + return(-1); } u_32_t getoptbyvalue(int optval) { struct ipopt_names *io; for (io = ionames; io->on_name; io++) if (io->on_value == optval) - return io->on_bit; - return -1; + return(io->on_bit); + return(-1); } diff --git a/sbin/ipf/libipf/parsefields.c b/sbin/ipf/libipf/parsefields.c index f79159f5419b..19a6d8b63d6d 100644 --- a/sbin/ipf/libipf/parsefields.c +++ b/sbin/ipf/libipf/parsefields.c @@ -1,51 +1,51 @@ #include "ipf.h" #include extern int nohdrfields; wordtab_t *parsefields(wordtab_t *table, char *arg) { wordtab_t *f, *fields; char *s, *t; int num; fields = NULL; num = 0; for (s = strtok(arg, ","); s != NULL; s = strtok(NULL, ",")) { t = strchr(s, '='); if (t != NULL) { *t++ = '\0'; if (*t == '\0') nohdrfields = 1; } f = findword(table, s); if (f == NULL) { fprintf(stderr, "Unknown field '%s'\n", s); exit(1); } num++; if (fields == NULL) { fields = malloc(2 * sizeof(*fields)); } else { fields = reallocarray(fields, num + 1, sizeof(*fields)); if (fields == NULL) { warnx("memory allocation error at %d in %s in %s", __LINE__, __FUNCTION__, __FILE__); abort(); } } if (t == NULL) { fields[num - 1].w_word = f->w_word; } else { fields[num - 1].w_word = t; } fields[num - 1].w_value = f->w_value; fields[num].w_word = NULL; fields[num].w_value = 0; } - return fields; + return(fields); } diff --git a/sbin/ipf/libipf/parseipfexpr.c b/sbin/ipf/libipf/parseipfexpr.c index 415c4b543a8e..c3bac34f71a1 100644 --- a/sbin/ipf/libipf/parseipfexpr.c +++ b/sbin/ipf/libipf/parseipfexpr.c @@ -1,281 +1,281 @@ #include "ipf.h" #include typedef struct ipfopentry { int ipoe_cmd; int ipoe_nbasearg; int ipoe_maxarg; int ipoe_argsize; char *ipoe_word; } ipfopentry_t; static ipfopentry_t opwords[17] = { { IPF_EXP_IP_ADDR, 2, 0, 1, "ip.addr" }, { IPF_EXP_IP6_ADDR, 2, 0, 4, "ip6.addr" }, { IPF_EXP_IP_PR, 1, 0, 1, "ip.p" }, { IPF_EXP_IP_SRCADDR, 2, 0, 1, "ip.src" }, { IPF_EXP_IP_DSTADDR, 2, 0, 1, "ip.dst" }, { IPF_EXP_IP6_SRCADDR, 2, 0, 4, "ip6.src" }, { IPF_EXP_IP6_DSTADDR, 2, 0, 4, "ip6.dst" }, { IPF_EXP_TCP_PORT, 1, 0, 1, "tcp.port" }, { IPF_EXP_TCP_DPORT, 1, 0, 1, "tcp.dport" }, { IPF_EXP_TCP_SPORT, 1, 0, 1, "tcp.sport" }, { IPF_EXP_TCP_FLAGS, 2, 0, 1, "tcp.flags" }, { IPF_EXP_UDP_PORT, 1, 0, 1, "udp.port" }, { IPF_EXP_UDP_DPORT, 1, 0, 1, "udp.dport" }, { IPF_EXP_UDP_SPORT, 1, 0, 1, "udp.sport" }, { IPF_EXP_TCP_STATE, 1, 0, 1, "tcp.state" }, { IPF_EXP_IDLE_GT, 1, 1, 1, "idle-gt" }, { -1, 0, 0, 0, NULL } }; int * parseipfexpr(char *line, char **errorptr) { int not, items, asize, *oplist, osize, i; char *temp, *arg, *s, *t, *ops, *error; ipfopentry_t *e; ipfexp_t *ipfe; asize = 0; error = NULL; oplist = NULL; temp = strdup(line); if (temp == NULL) { error = "strdup failed"; goto parseerror; } /* * Eliminate any white spaces to make parsing easier. */ for (s = temp; *s != '\0'; ) { if (ISSPACE(*s)) strcpy(s, s + 1); else s++; } /* * Parse the string. * It should be sets of "ip.dst=1.2.3.4/32;" things. * There must be a "=" or "!=" and it must end in ";". */ if (temp[strlen(temp) - 1] != ';') { error = "last character not ';'"; goto parseerror; } /* * Work through the list of complete operands present. */ for (ops = strtok(temp, ";"); ops != NULL; ops = strtok(NULL, ";")) { arg = strchr(ops, '='); if ((arg < ops + 2) || (arg == NULL)) { error = "bad 'arg' vlaue"; goto parseerror; } if (*(arg - 1) == '!') { *(arg - 1) = '\0'; not = 1; } else { not = 0; } *arg++ = '\0'; for (e = opwords; e->ipoe_word; e++) { if (strcmp(ops, e->ipoe_word) == 0) break; } if (e->ipoe_word == NULL) { error = malloc(32); if (error != NULL) { snprintf(error, sizeof(error), "keyword (%.10s) not found", ops); } goto parseerror; } /* * Count the number of commas so we know how big to * build the array */ for (s = arg, items = 1; *s != '\0'; s++) if (*s == ',') items++; if ((e->ipoe_maxarg != 0) && (items > e->ipoe_maxarg)) { error = "too many items"; goto parseerror; } /* * osize will mark the end of where we have filled up to * and is thus where we start putting new data. */ osize = asize; asize += 4 + (items * e->ipoe_nbasearg * e->ipoe_argsize); if (oplist == NULL) oplist = calloc(asize + 2, sizeof(int)); else oplist = reallocarray(oplist, asize + 2, sizeof(int)); if (oplist == NULL) { error = "oplist alloc failed"; goto parseerror; } ipfe = (ipfexp_t *)(oplist + osize); osize += 4; ipfe->ipfe_cmd = e->ipoe_cmd; ipfe->ipfe_not = not; ipfe->ipfe_narg = items * e->ipoe_nbasearg; ipfe->ipfe_size = items * e->ipoe_nbasearg * e->ipoe_argsize; ipfe->ipfe_size += 4; for (s = arg; (*s != '\0') && (osize < asize); s = t) { /* * Look for the end of this arg or the ',' to say * there is another following. */ for (t = s; (*t != '\0') && (*t != ','); t++) ; if (*t == ',') *t++ = '\0'; if (!strcasecmp(ops, "ip.addr") || !strcasecmp(ops, "ip.src") || !strcasecmp(ops, "ip.dst")) { i6addr_t mask, addr; char *delim; delim = strchr(s, '/'); if (delim != NULL) { *delim++ = '\0'; if (genmask(AF_INET, delim, &mask) == -1) { error = "genmask failed"; goto parseerror; } } else { mask.in4.s_addr = 0xffffffff; } if (gethost(AF_INET, s, &addr) == -1) { error = "gethost failed"; goto parseerror; } oplist[osize++] = addr.in4.s_addr; oplist[osize++] = mask.in4.s_addr; #ifdef USE_INET6 } else if (!strcasecmp(ops, "ip6.addr") || !strcasecmp(ops, "ip6.src") || !strcasecmp(ops, "ip6.dst")) { i6addr_t mask, addr; char *delim; delim = strchr(s, '/'); if (delim != NULL) { *delim++ = '\0'; if (genmask(AF_INET6, delim, &mask) == -1) { error = "genmask failed"; goto parseerror; } } else { mask.i6[0] = 0xffffffff; mask.i6[1] = 0xffffffff; mask.i6[2] = 0xffffffff; mask.i6[3] = 0xffffffff; } if (gethost(AF_INET6, s, &addr) == -1) { error = "gethost failed"; goto parseerror; } oplist[osize++] = addr.i6[0]; oplist[osize++] = addr.i6[1]; oplist[osize++] = addr.i6[2]; oplist[osize++] = addr.i6[3]; oplist[osize++] = mask.i6[0]; oplist[osize++] = mask.i6[1]; oplist[osize++] = mask.i6[2]; oplist[osize++] = mask.i6[3]; #endif } else if (!strcasecmp(ops, "ip.p")) { int p; p = getproto(s); if (p == -1) goto parseerror; oplist[osize++] = p; } else if (!strcasecmp(ops, "tcp.flags")) { u_32_t mask, flags; char *delim; delim = strchr(s, '/'); if (delim != NULL) { *delim++ = '\0'; mask = tcpflags(delim); } else { mask = 0xff; } flags = tcpflags(s); oplist[osize++] = flags; oplist[osize++] = mask; } else if (!strcasecmp(ops, "tcp.port") || !strcasecmp(ops, "tcp.sport") || !strcasecmp(ops, "tcp.dport") || !strcasecmp(ops, "udp.port") || !strcasecmp(ops, "udp.sport") || !strcasecmp(ops, "udp.dport")) { char proto[4]; u_short port; strncpy(proto, ops, 3); proto[3] = '\0'; if (getport(NULL, s, &port, proto) == -1) goto parseerror; oplist[osize++] = port; } else if (!strcasecmp(ops, "tcp.state")) { oplist[osize++] = atoi(s); } else { error = "unknown word"; goto parseerror; } } } free(temp); if (errorptr != NULL) *errorptr = NULL; for (i = asize; i > 0; i--) oplist[i] = oplist[i - 1]; oplist[0] = asize + 2; oplist[asize + 1] = IPF_EXP_END; - return oplist; + return(oplist); parseerror: if (errorptr != NULL) *errorptr = error; if (oplist != NULL) free(oplist); if (temp != NULL) free(temp); - return NULL; + return(NULL); } diff --git a/sbin/ipf/libipf/parsewhoisline.c b/sbin/ipf/libipf/parsewhoisline.c index eb26a3efa348..ddcb8677cc1c 100644 --- a/sbin/ipf/libipf/parsewhoisline.c +++ b/sbin/ipf/libipf/parsewhoisline.c @@ -1,129 +1,129 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: parsewhoisline.c,v 1.2.2.5 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" /* Microsoft Corp MICROSOFT19 (NET-198-136-97-0-1) 198.137.97.0 - 198.137.97.255 Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47 */ int parsewhoisline(char *line, addrfamily_t *addrp, addrfamily_t *maskp) { struct in_addr a1, a2; char *src = line; char *s = NULL; if (line == NULL) - return -1; + return(-1); while (*src != '\0') { s = strchr(src, '('); if (s == NULL) break; if (strncmp(s, "(NET", 4)) { src = s + 1; } break; } if (s == NULL) - return -1; + return(-1); memset(addrp, 0x00, sizeof(*maskp)); memset(maskp, 0x00, sizeof(*maskp)); if (*(s + 4) == '6') { #ifdef USE_INET6 i6addr_t a61, a62; s = strchr(s, ')'); if (s == NULL || *++s != ' ') - return -1; + return(-1); /* * Parse the IPv6 */ if (inet_pton(AF_INET6, s, &a61.in6) != 1) - return -1; + return(-1); s = strchr(s, ' '); if (s == NULL || strncmp(s, " - ", 3)) - return -1; + return(-1); s += 3; if (inet_pton(AF_INET6, s, &a62) != 1) - return -1; + return(-1); addrp->adf_addr = a61; addrp->adf_family = AF_INET6; addrp->adf_len = offsetof(addrfamily_t, adf_addr) + sizeof(struct in6_addr); maskp->adf_addr.i6[0] = ~(a62.i6[0] ^ a61.i6[0]); maskp->adf_addr.i6[1] = ~(a62.i6[1] ^ a61.i6[1]); maskp->adf_addr.i6[2] = ~(a62.i6[2] ^ a61.i6[2]); maskp->adf_addr.i6[3] = ~(a62.i6[3] ^ a61.i6[3]); /* * If the mask that's been generated isn't a consecutive mask * then we can't add it into a pool. */ if (count6bits(maskp->adf_addr.i6) == -1) - return -1; + return(-1); maskp->adf_family = AF_INET6; maskp->adf_len = addrp->adf_len; if (IP6_MASKNEQ(&addrp->adf_addr.in6, &maskp->adf_addr.in6, &addrp->adf_addr.in6)) { - return -1; + return(-1); } - return 0; + return(0); #else - return -1; + return(-1); #endif } s = strchr(s, ')'); if (s == NULL || *++s != ' ') - return -1; + return(-1); s++; if (inet_aton(s, &a1) != 1) - return -1; + return(-1); s = strchr(s, ' '); if (s == NULL || strncmp(s, " - ", 3)) - return -1; + return(-1); s += 3; if (inet_aton(s, &a2) != 1) - return -1; + return(-1); addrp->adf_addr.in4 = a1; addrp->adf_family = AF_INET; addrp->adf_len = offsetof(addrfamily_t, adf_addr) + sizeof(struct in_addr); maskp->adf_addr.in4.s_addr = ~(a2.s_addr ^ a1.s_addr); /* * If the mask that's been generated isn't a consecutive mask then * we can't add it into a pool. */ if (count4bits(maskp->adf_addr.in4.s_addr) == -1) - return -1; + return(-1); maskp->adf_family = AF_INET; maskp->adf_len = addrp->adf_len; bzero((char *)maskp + maskp->adf_len, sizeof(*maskp) - maskp->adf_len); if ((addrp->adf_addr.in4.s_addr & maskp->adf_addr.in4.s_addr) != addrp->adf_addr.in4.s_addr) - return -1; - return 0; + return(-1); + return(0); } diff --git a/sbin/ipf/libipf/poolio.c b/sbin/ipf/libipf/poolio.c index 83cfb8cf5047..316bf49975ef 100644 --- a/sbin/ipf/libipf/poolio.c +++ b/sbin/ipf/libipf/poolio.c @@ -1,53 +1,53 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: poolio.c,v 1.1.2.3 2012/07/22 08:04:24 darren_r Exp $ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" static int poolfd = -1; int pool_open(void) { if ((opts & OPT_DONTOPEN) != 0) - return 0; + return(0); if (poolfd == -1) poolfd = open(IPLOOKUP_NAME, O_RDWR); - return poolfd; + return(poolfd); } int pool_ioctl(iocfunc, cmd, ptr) ioctlfunc_t iocfunc; ioctlcmd_t cmd; void *ptr; { - return (*iocfunc)(poolfd, cmd, ptr); + return(*iocfunc)(poolfd, cmd, ptr); } void pool_close(void) { if (poolfd != -1) { close(poolfd); poolfd = -1; } } int pool_fd(void) { - return poolfd; + return(poolfd); } diff --git a/sbin/ipf/libipf/portname.c b/sbin/ipf/libipf/portname.c index f567b26fc3fd..bdc9e21432b3 100644 --- a/sbin/ipf/libipf/portname.c +++ b/sbin/ipf/libipf/portname.c @@ -1,43 +1,43 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" char * portname(int pr, int port) { static char buf[32]; struct protoent *p = NULL; struct servent *sv = NULL; struct servent *sv1 = NULL; if ((opts & OPT_NORESOLVE) == 0) { if (pr == -1) { if ((sv = getservbyport(htons(port), "tcp"))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; sv1 = getservbyport(htons(port), "udp"); sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? NULL : sv1; } if (sv) - return (buf); + return(buf); } else if ((pr != -2) && (p = getprotobynumber(pr))) { if ((sv = getservbyport(htons(port), p->p_name))) { strncpy(buf, sv->s_name, sizeof(buf)-1); buf[sizeof(buf)-1] = '\0'; - return (buf); + return(buf); } } } (void) snprintf(buf, sizeof(buf), "%d", port); - return (buf); + return(buf); } diff --git a/sbin/ipf/libipf/prependmbt.c b/sbin/ipf/libipf/prependmbt.c index 871e46be15a2..c6e2868053b3 100644 --- a/sbin/ipf/libipf/prependmbt.c +++ b/sbin/ipf/libipf/prependmbt.c @@ -1,16 +1,16 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: prependmbt.c,v 1.3.2.3 2012/07/22 08:04:24 darren_r Exp $ */ #include "ipf.h" int prependmbt( fr_info_t *fin, mb_t *m) { m->mb_next = *fin->fin_mp; *fin->fin_mp = m; - return 0; + return(0); } diff --git a/sbin/ipf/libipf/printdstl_live.c b/sbin/ipf/libipf/printdstl_live.c index 684da8f0003a..a7c37c5f4f81 100644 --- a/sbin/ipf/libipf/printdstl_live.c +++ b/sbin/ipf/libipf/printdstl_live.c @@ -1,80 +1,80 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include "ipf.h" #include "netinet/ipl.h" /* * Because the ipf_dstnode_t can vary in size because of the interface name, * the size may be larger than just sizeof(). */ ippool_dst_t * printdstl_live( ippool_dst_t *d, int fd, char *name, int opts, wordtab_t *fields) { ipf_dstnode_t *entry, *zero; ipflookupiter_t iter; int printed, last; ipfobj_t obj; if ((name != NULL) && strncmp(name, d->ipld_name, FR_GROUPLEN)) - return d->ipld_next; + return(d->ipld_next); entry = calloc(1, sizeof(*entry) + 64); if (entry == NULL) - return d->ipld_next; + return(d->ipld_next); zero = calloc(1, sizeof(*zero) + 64); if (zero == NULL) { free(entry); - return d->ipld_next; + return(d->ipld_next); } if (fields == NULL) printdstlistdata(d, opts); if ((d->ipld_flags & IPHASH_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_LOOKUPITER; obj.ipfo_ptr = &iter; obj.ipfo_size = sizeof(iter); iter.ili_data = entry; iter.ili_type = IPLT_DSTLIST; iter.ili_otype = IPFLOOKUPITER_NODE; iter.ili_ival = IPFGENITER_LOOKUP; iter.ili_unit = d->ipld_unit; strncpy(iter.ili_name, d->ipld_name, FR_GROUPLEN); last = 0; printed = 0; while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { if (entry->ipfd_next == NULL) last = 1; if (bcmp((char *)zero, (char *)entry, sizeof(*zero)) == 0) break; (void) printdstlistnode(entry, bcopywrap, opts, fields); printed++; } (void) ioctl(fd, SIOCIPFDELTOK, &iter.ili_key); free(entry); free(zero); if (printed == 0) putchar(';'); if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - return d->ipld_next; + return(d->ipld_next); } diff --git a/sbin/ipf/libipf/printdstlist.c b/sbin/ipf/libipf/printdstlist.c index 6468e6ca8ef6..a4f9e0ec3db4 100644 --- a/sbin/ipf/libipf/printdstlist.c +++ b/sbin/ipf/libipf/printdstlist.c @@ -1,55 +1,55 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" ippool_dst_t * printdstlist( ippool_dst_t *pp, copyfunc_t copyfunc, char *name, int opts, ipf_dstnode_t *nodes, wordtab_t *fields) { ipf_dstnode_t *node; ippool_dst_t dst; if ((*copyfunc)(pp, &dst, sizeof(dst))) - return NULL; + return(NULL); if ((name != NULL) && strncmp(name, dst.ipld_name, FR_GROUPLEN)) - return dst.ipld_next; + return(dst.ipld_next); if (fields == NULL) printdstlistdata(&dst, opts); if ((dst.ipld_flags & IPDST_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); if (nodes == NULL) { putchar(';'); } else { for (node = nodes; node != NULL; ) { ipf_dstnode_t *n; n = calloc(1, node->ipfd_size); if (n == NULL) break; if ((*copyfunc)(node, n, node->ipfd_size)) { free(n); - return NULL; + return(NULL); } node = printdstlistnode(n, bcopywrap, opts, fields); free(n); } } if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - return dst.ipld_next; + return(dst.ipld_next); } diff --git a/sbin/ipf/libipf/printdstlistnode.c b/sbin/ipf/libipf/printdstlistnode.c index 1728a5b88594..4a83236848ef 100644 --- a/sbin/ipf/libipf/printdstlistnode.c +++ b/sbin/ipf/libipf/printdstlistnode.c @@ -1,75 +1,75 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" ipf_dstnode_t * printdstlistnode(ipf_dstnode_t *inp, copyfunc_t copyfunc, int opts, wordtab_t *fields) { ipf_dstnode_t node, *np; int i; #ifdef USE_INET6 char buf[INET6_ADDRSTRLEN+1]; const char *str; #endif if ((*copyfunc)(inp, &node, sizeof(node))) - return NULL; + return(NULL); np = calloc(1, node.ipfd_size); if (np == NULL) - return node.ipfd_next; + return(node.ipfd_next); if ((*copyfunc)(inp, np, node.ipfd_size)) - return NULL; + return(NULL); if (fields != NULL) { for (i = 0; fields[i].w_value != 0; i++) { printpoolfield(np, IPLT_DSTLIST, i); if (fields[i + 1].w_value != 0) printf("\t"); } printf("\n"); } else if ((opts & OPT_DEBUG) == 0) { putchar(' '); if (np->ipfd_dest.fd_name >= 0) PRINTF("%s:", np->ipfd_names); if (np->ipfd_dest.fd_addr.adf_family == AF_INET) { printip(AF_INET, (u_32_t *)&np->ipfd_dest.fd_ip); } else { #ifdef USE_INET6 str = inet_ntop(AF_INET6, &np->ipfd_dest.fd_ip6, buf, sizeof(buf) - 1); if (str != NULL) PRINTF("%s", str); #endif } putchar(';'); } else { PRINTF("Interface: [%s]/%d\n", np->ipfd_names, np->ipfd_dest.fd_name); #ifdef USE_INET6 str = inet_ntop(np->ipfd_dest.fd_addr.adf_family, &np->ipfd_dest.fd_ip6, buf, sizeof(buf) - 1); if (str != NULL) { PRINTF("\tAddress: %s\n", str); } #else PRINTF("\tAddress: %s\n", inet_ntoa(np->ipfd_dest.fd_ip)); #endif PRINTF( #ifdef USE_QUAD_T "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", #else "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", #endif np->ipfd_states, np->ipfd_ref, np->ipfd_names, np->ipfd_uid); } free(np); - return node.ipfd_next; + return(node.ipfd_next); } diff --git a/sbin/ipf/libipf/printhash.c b/sbin/ipf/libipf/printhash.c index 6961cb170f60..f5eb2669aa6b 100644 --- a/sbin/ipf/libipf/printhash.c +++ b/sbin/ipf/libipf/printhash.c @@ -1,54 +1,54 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" iphtable_t * printhash( iphtable_t *hp, copyfunc_t copyfunc, char *name, int opts, wordtab_t *fields) { iphtent_t *ipep, **table; iphtable_t iph; int printed; size_t sz; if ((*copyfunc)((char *)hp, (char *)&iph, sizeof(iph))) - return NULL; + return(NULL); if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN)) - return iph.iph_next; + return(iph.iph_next); if (fields == NULL) printhashdata(hp, opts); if ((hp->iph_flags & IPHASH_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); sz = iph.iph_size * sizeof(*table); table = malloc(sz); if ((*copyfunc)((char *)iph.iph_table, (char *)table, sz)) - return NULL; + return(NULL); for (printed = 0, ipep = iph.iph_list; ipep != NULL; ) { ipep = printhashnode(&iph, ipep, copyfunc, opts, fields); printed++; } if (printed == 0) putchar(';'); free(table); if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - return iph.iph_next; + return(iph.iph_next); } diff --git a/sbin/ipf/libipf/printhash_live.c b/sbin/ipf/libipf/printhash_live.c index edf85675474a..b3e2987cf0ad 100644 --- a/sbin/ipf/libipf/printhash_live.c +++ b/sbin/ipf/libipf/printhash_live.c @@ -1,65 +1,65 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include "ipf.h" #include "netinet/ipl.h" iphtable_t * printhash_live(iphtable_t *hp, int fd, char *name, int opts, wordtab_t *fields) { iphtent_t entry, zero; ipflookupiter_t iter; int last, printed; ipfobj_t obj; if ((name != NULL) && strncmp(name, hp->iph_name, FR_GROUPLEN)) - return hp->iph_next; + return(hp->iph_next); if (fields == NULL) printhashdata(hp, opts); if ((hp->iph_flags & IPHASH_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_LOOKUPITER; obj.ipfo_ptr = &iter; obj.ipfo_size = sizeof(iter); iter.ili_data = &entry; iter.ili_type = IPLT_HASH; iter.ili_otype = IPFLOOKUPITER_NODE; iter.ili_ival = IPFGENITER_LOOKUP; iter.ili_unit = hp->iph_unit; strncpy(iter.ili_name, hp->iph_name, FR_GROUPLEN); last = 0; printed = 0; bzero((char *)&zero, sizeof(zero)); while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { if (entry.ipe_next == NULL) last = 1; if (bcmp(&zero, &entry, sizeof(zero)) == 0) break; (void) printhashnode(hp, &entry, bcopywrap, opts, fields); printed++; } if (last == 0) ipferror(fd, "walking hash nodes"); if (printed == 0) putchar(';'); if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - return hp->iph_next; + return(hp->iph_next); } diff --git a/sbin/ipf/libipf/printhashnode.c b/sbin/ipf/libipf/printhashnode.c index 18cd7a1d9f84..4ece4a8dd90d 100644 --- a/sbin/ipf/libipf/printhashnode.c +++ b/sbin/ipf/libipf/printhashnode.c @@ -1,94 +1,94 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" iphtent_t * printhashnode(iphtable_t *iph, iphtent_t *ipep, copyfunc_t copyfunc, int opts, wordtab_t *fields) { iphtent_t ipe; u_int hv; int i; if ((*copyfunc)(ipep, &ipe, sizeof(ipe))) - return NULL; + return(NULL); hv = IPE_V4_HASH_FN(ipe.ipe_addr.i6[0], ipe.ipe_mask.i6[0], iph->iph_size); if (fields != NULL) { for (i = 0; fields[i].w_value != 0; i++) { printpoolfield(&ipe, IPLT_HASH, i); if (fields[i + 1].w_value != 0) printf("\t"); } printf("\n"); } else if ((opts & OPT_DEBUG) != 0) { #ifdef USE_INET6 if (ipe.ipe_family == AF_INET6) { char buf[INET6_ADDRSTRLEN + 1]; const char *str; buf[0] = '\0'; str = inet_ntop(AF_INET6, &ipe.ipe_addr.in6, buf, sizeof(buf) - 1); if (str == NULL) str = "???"; PRINTF("\t%d\tAddress: %s", hv, str); printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, ipe.ipe_group); #ifdef USE_QUAD_T PRINTF("\tHits: %"PRIu64"\tBytes: %"PRIu64"\n", ipe.ipe_hits, ipe.ipe_bytes); #else PRINTF("\tHits: %lu\tBytes: %lu\n", ipe.ipe_hits, ipe.ipe_bytes); #endif /* USE_QUAD_T */ } else if (ipe.ipe_family == AF_INET) { #else if (ipe.ipe_family == AF_INET) { #endif /* USE_INET6 */ PRINTF("\t%d\tAddress: %s", hv, inet_ntoa(ipe.ipe_addr.in4)); printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, ipe.ipe_group); #ifdef USE_QUAD_T PRINTF("\tHits: %"PRIu64"\tBytes: %"PRIu64"\n", ipe.ipe_hits, ipe.ipe_bytes); #else PRINTF("\tHits: %lu\tBytes: %lu\n", ipe.ipe_hits, ipe.ipe_bytes); #endif /* USE_QUAD_T */ } else { PRINTF("\tAddress: family: %d\n", ipe.ipe_family); } } else { putchar(' '); printip(ipe.ipe_family, (u_32_t *)&ipe.ipe_addr.in4_addr); printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); if (ipe.ipe_value != 0) { switch (iph->iph_type & ~IPHASH_ANON) { case IPHASH_GROUPMAP : if (strncmp(ipe.ipe_group, iph->iph_name, FR_GROUPLEN)) PRINTF(", group=%s", ipe.ipe_group); break; } } putchar(';'); } ipep = ipe.ipe_next; - return ipep; + return(ipep); } diff --git a/sbin/ipf/libipf/printpool.c b/sbin/ipf/libipf/printpool.c index ccbfd84d3b67..319e52af7dba 100644 --- a/sbin/ipf/libipf/printpool.c +++ b/sbin/ipf/libipf/printpool.c @@ -1,61 +1,61 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" ip_pool_t * printpool(ip_pool_t *pp, copyfunc_t copyfunc, char *name, int opts, wordtab_t *fields) { ip_pool_node_t *ipnp, *ipnpn, ipn, **pnext; ip_pool_t ipp; if ((*copyfunc)(pp, &ipp, sizeof(ipp))) - return NULL; + return(NULL); if ((name != NULL) && strncmp(name, ipp.ipo_name, FR_GROUPLEN)) - return ipp.ipo_next; + return(ipp.ipo_next); printpooldata(&ipp, opts); if ((ipp.ipo_flags & IPOOL_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); ipnpn = ipp.ipo_list; ipp.ipo_list = NULL; pnext = &ipp.ipo_list; while (ipnpn != NULL) { ipnp = (ip_pool_node_t *)malloc(sizeof(*ipnp)); (*copyfunc)(ipnpn, ipnp, sizeof(ipn)); ipnpn = ipnp->ipn_next; *pnext = ipnp; pnext = &ipnp->ipn_next; ipnp->ipn_next = NULL; } if (ipp.ipo_list == NULL) { putchar(';'); } else { for (ipnp = ipp.ipo_list; ipnp != NULL; ipnp = ipnpn) { ipnpn = printpoolnode(ipnp, opts, fields); free(ipnp); if ((opts & OPT_DEBUG) == 0) { putchar(';'); } } } if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); - return ipp.ipo_next; + return(ipp.ipo_next); } diff --git a/sbin/ipf/libipf/printpool_live.c b/sbin/ipf/libipf/printpool_live.c index 15f563277309..1eb5079c815e 100644 --- a/sbin/ipf/libipf/printpool_live.c +++ b/sbin/ipf/libipf/printpool_live.c @@ -1,67 +1,67 @@ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include #include "ipf.h" #include "netinet/ipl.h" ip_pool_t * printpool_live(ip_pool_t *pool, int fd, char *name, int opts, wordtab_t *fields) { ip_pool_node_t entry; ipflookupiter_t iter; int printed, last; ipfobj_t obj; if ((name != NULL) && strncmp(name, pool->ipo_name, FR_GROUPLEN)) - return pool->ipo_next; + return(pool->ipo_next); if (fields == NULL) printpooldata(pool, opts); if ((pool->ipo_flags & IPOOL_DELETE) != 0) PRINTF("# "); if ((opts & OPT_DEBUG) == 0) PRINTF("\t{"); obj.ipfo_rev = IPFILTER_VERSION; obj.ipfo_type = IPFOBJ_LOOKUPITER; obj.ipfo_ptr = &iter; obj.ipfo_size = sizeof(iter); iter.ili_data = &entry; iter.ili_type = IPLT_POOL; iter.ili_otype = IPFLOOKUPITER_NODE; iter.ili_ival = IPFGENITER_LOOKUP; iter.ili_unit = pool->ipo_unit; strncpy(iter.ili_name, pool->ipo_name, FR_GROUPLEN); last = 0; printed = 0; if (pool->ipo_list != NULL) { while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { if (entry.ipn_next == NULL) last = 1; (void) printpoolnode(&entry, opts, fields); if ((opts & OPT_DEBUG) == 0) putchar(';'); printed++; } } if (printed == 0) putchar(';'); if ((opts & OPT_DEBUG) == 0) PRINTF(" };\n"); (void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key); - return pool->ipo_next; + return(pool->ipo_next); } diff --git a/sbin/ipf/libipf/printpoolnode.c b/sbin/ipf/libipf/printpoolnode.c index 4198603c7548..8703a91a0ca1 100644 --- a/sbin/ipf/libipf/printpoolnode.c +++ b/sbin/ipf/libipf/printpoolnode.c @@ -1,68 +1,68 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" ip_pool_node_t * printpoolnode(ip_pool_node_t *np, int opts, wordtab_t *fields) { int i; if (fields != NULL) { for (i = 0; fields[i].w_value != 0; i++) { printpoolfield(np, IPLT_POOL, i); if (fields[i + 1].w_value != 0) printf("\t"); } printf("\n"); } else if ((opts & OPT_DEBUG) == 0) { putchar(' '); if (np->ipn_info == 1) PRINTF("! "); printip(np->ipn_addr.adf_family, (u_32_t *)&np->ipn_addr.adf_addr.in4); printmask(np->ipn_addr.adf_family, (u_32_t *)&np->ipn_mask.adf_addr); } else { #ifdef USE_INET6 if (np->ipn_addr.adf_family == AF_INET6) { char buf[INET6_ADDRSTRLEN + 1]; const char *str; buf[0] = '\0'; str = inet_ntop(AF_INET6, &np->ipn_addr.adf_addr.in6, buf, sizeof(buf) - 1); if (str == NULL) str = "???"; PRINTF("\tAddress: %s%s", np->ipn_info ? "! " : "", str); } else if (np->ipn_addr.adf_family == AF_INET) { #else if (np->ipn_addr.adf_family == AF_INET) { #endif PRINTF("\tAddress: %s%s", np->ipn_info ? "! " : "", inet_ntoa(np->ipn_addr.adf_addr.in4)); } else { PRINTF("\tAddress: family: %d\n", np->ipn_addr.adf_family); } printmask(np->ipn_addr.adf_family, (u_32_t *)&np->ipn_mask.adf_addr); #ifdef USE_QUAD_T PRINTF("\n\t\tHits %"PRIu64"\tBytes %"PRIu64"\tName %s\tRef %d\n", np->ipn_hits, np->ipn_bytes, np->ipn_name, np->ipn_ref); #else PRINTF("\n\t\tHits %lu\tBytes %lu\tName %s\tRef %d\n", np->ipn_hits, np->ipn_bytes, np->ipn_name, np->ipn_ref); #endif } - return np->ipn_next; + return(np->ipn_next); } diff --git a/sbin/ipf/libipf/printstate.c b/sbin/ipf/libipf/printstate.c index 8832a723e9f1..1a55f84afd63 100644 --- a/sbin/ipf/libipf/printstate.c +++ b/sbin/ipf/libipf/printstate.c @@ -1,221 +1,221 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ #include "ipf.h" #include "kmem.h" ipstate_t * printstate(ipstate_t *sp, int opts, u_long now) { struct protoent *pr; synclist_t ipsync; if ((opts & OPT_NORESOLVE) == 0) pr = getprotobynumber(sp->is_p); else pr = NULL; PRINTF("%d:", sp->is_v); if (pr != NULL) PRINTF("%s", pr->p_name); else PRINTF("%d", sp->is_p); PRINTF(" src:%s", hostname(sp->is_family, &sp->is_src.in4)); if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { if (sp->is_flags & IS_WSPORT) PRINTF(",*"); else PRINTF(",%d", ntohs(sp->is_sport)); } PRINTF(" dst:%s", hostname(sp->is_family, &sp->is_dst.in4)); if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { if (sp->is_flags & IS_WDPORT) PRINTF(",*"); else PRINTF(",%d", ntohs(sp->is_dport)); } if (sp->is_p == IPPROTO_TCP) { PRINTF(" state:%d/%d", sp->is_state[0], sp->is_state[1]); } PRINTF(" %ld", sp->is_die - now); if (sp->is_phnext == NULL) PRINTF(" ORPHAN"); if (sp->is_flags & IS_CLONE) PRINTF(" CLONE"); putchar('\n'); if (sp->is_p == IPPROTO_TCP) { PRINTF("\t%x:%x %hu<<%d:%hu<<%d\n", sp->is_send, sp->is_dend, sp->is_maxswin, sp->is_swinscale, sp->is_maxdwin, sp->is_dwinscale); if ((opts & OPT_VERBOSE) != 0) { PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n", sp->is_smsk[0], sp->is_smsk[1], sp->is_isc, sp->is_s0[0], sp->is_s0[1]); PRINTF("\tFWD: ISN inc %x sumd %x\n", sp->is_isninc[0], sp->is_sumd[0]); PRINTF("\tREV: ISN inc %x sumd %x\n", sp->is_isninc[1], sp->is_sumd[1]); #ifdef IPFILTER_SCAN PRINTF("\tsbuf[0] ["); printsbuf(sp->is_sbuf[0]); PRINTF("] sbuf[1] ["); printsbuf(sp->is_sbuf[1]); PRINTF("]\n"); #endif } } else if (sp->is_p == IPPROTO_GRE) { PRINTF("\tcall %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]), ntohs(sp->is_gre.gs_call[1])); } else if (sp->is_p == IPPROTO_ICMP #ifdef USE_INET6 || sp->is_p == IPPROTO_ICMPV6 #endif ) { PRINTF("\tid %hu seq %hu type %d\n", sp->is_icmp.ici_id, sp->is_icmp.ici_seq, sp->is_icmp.ici_type); } #ifdef USE_QUAD_T PRINTF("\tFWD: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n\tREV: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n", sp->is_pkts[0], sp->is_bytes[0], sp->is_pkts[1], sp->is_bytes[1], sp->is_pkts[2], sp->is_bytes[2], sp->is_pkts[3], sp->is_bytes[3]); #else PRINTF("\tFWD: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n\tREV: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n", sp->is_pkts[0], sp->is_bytes[0], sp->is_pkts[1], sp->is_bytes[1], sp->is_pkts[2], sp->is_bytes[2], sp->is_pkts[3], sp->is_bytes[3]); #endif PRINTF("\ttag %u pass %#x = ", sp->is_tag, sp->is_pass); /* * Print out bits set in the result code for the state being * kept as they would for a rule. */ if (FR_ISPASS(sp->is_pass)) { PRINTF("pass"); } else if (FR_ISBLOCK(sp->is_pass)) { PRINTF("block"); switch (sp->is_pass & FR_RETMASK) { case FR_RETICMP : PRINTF(" return-icmp"); break; case FR_FAKEICMP : PRINTF(" return-icmp-as-dest"); break; case FR_RETRST : PRINTF(" return-rst"); break; default : break; } } else if ((sp->is_pass & FR_LOGMASK) == FR_LOG) { PRINTF("log"); if (sp->is_pass & FR_LOGBODY) PRINTF(" body"); if (sp->is_pass & FR_LOGFIRST) PRINTF(" first"); } else if (FR_ISACCOUNT(sp->is_pass)) { PRINTF("count"); } else if (FR_ISPREAUTH(sp->is_pass)) { PRINTF("preauth"); } else if (FR_ISAUTH(sp->is_pass)) PRINTF("auth"); if (sp->is_pass & FR_OUTQUE) PRINTF(" out"); else PRINTF(" in"); if ((sp->is_pass & FR_LOG) != 0) { PRINTF(" log"); if (sp->is_pass & FR_LOGBODY) PRINTF(" body"); if (sp->is_pass & FR_LOGFIRST) PRINTF(" first"); if (sp->is_pass & FR_LOGORBLOCK) PRINTF(" or-block"); } if (sp->is_pass & FR_QUICK) PRINTF(" quick"); if (sp->is_pass & FR_KEEPFRAG) PRINTF(" keep frags"); /* a given; no? */ if (sp->is_pass & FR_KEEPSTATE) { PRINTF(" keep state"); if (sp->is_pass & (FR_STATESYNC|FR_STSTRICT|FR_STLOOSE)) { PRINTF(" ("); if (sp->is_pass & FR_STATESYNC) PRINTF(" sync"); if (sp->is_pass & FR_STSTRICT) PRINTF(" strict"); if (sp->is_pass & FR_STLOOSE) PRINTF(" loose"); PRINTF(" )"); } } PRINTF("\n"); if ((opts & OPT_VERBOSE) != 0) { PRINTF("\tref %d", sp->is_ref); PRINTF(" pkt_flags & %x(%x) = %x\n", sp->is_flags & 0xf, sp->is_flags, sp->is_flags >> 4); PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0], sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]); PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", sp->is_secmsk, sp->is_sec, sp->is_authmsk, sp->is_auth); PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0], sp->is_flx[0][1], sp->is_flx[1][0], sp->is_flx[1][1]); } PRINTF("\tinterfaces: in %s[%s", getifname(sp->is_ifp[0]), sp->is_ifname[0]); if (opts & OPT_DEBUG) PRINTF("/%p", sp->is_ifp[0]); putchar(']'); PRINTF(",%s[%s", getifname(sp->is_ifp[1]), sp->is_ifname[1]); if (opts & OPT_DEBUG) PRINTF("/%p", sp->is_ifp[1]); putchar(']'); PRINTF(" out %s[%s", getifname(sp->is_ifp[2]), sp->is_ifname[2]); if (opts & OPT_DEBUG) PRINTF("/%p", sp->is_ifp[2]); putchar(']'); PRINTF(",%s[%s", getifname(sp->is_ifp[3]), sp->is_ifname[3]); if (opts & OPT_DEBUG) PRINTF("/%p", sp->is_ifp[3]); PRINTF("]\n"); PRINTF("\tSync status: "); if (sp->is_sync != NULL) { if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync, sizeof(ipsync))) { PRINTF("status could not be retrieved\n"); - return (NULL); + return(NULL); } PRINTF("idx %d num %d v %d pr %d rev %d\n", ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v, ipsync.sl_p, ipsync.sl_rev); } else { PRINTF("not synchronized\n"); } - return (sp->is_next); + return(sp->is_next); } diff --git a/sbin/ipf/libipf/remove_hash.c b/sbin/ipf/libipf/remove_hash.c index e76a4aca612b..5a0b464617de 100644 --- a/sbin/ipf/libipf/remove_hash.c +++ b/sbin/ipf/libipf/remove_hash.c @@ -1,48 +1,48 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" int remove_hash(iphtable_t *iphp, ioctlfunc_t iocfunc) { iplookupop_t op; iphtable_t iph; if (pool_open() == -1) - return -1; + return(-1); op.iplo_type = IPLT_HASH; op.iplo_unit = iphp->iph_unit; strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name)); if (*op.iplo_name == '\0') op.iplo_arg = IPHASH_ANON; op.iplo_size = sizeof(iph); op.iplo_struct = &iph; bzero((char *)&iph, sizeof(iph)); iph.iph_unit = iphp->iph_unit; iph.iph_type = iphp->iph_type; strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); iph.iph_flags = iphp->iph_flags; if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "remove lookup hash table"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash table")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/remove_hashnode.c b/sbin/ipf/libipf/remove_hashnode.c index f9d796472b1e..c289408273de 100644 --- a/sbin/ipf/libipf/remove_hashnode.c +++ b/sbin/ipf/libipf/remove_hashnode.c @@ -1,52 +1,52 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" int remove_hashnode(int unit, char *name, iphtent_t *node, ioctlfunc_t iocfunc) { iplookupop_t op; iphtent_t ipe; if (pool_open() == -1) - return -1; + return(-1); op.iplo_type = IPLT_HASH; op.iplo_unit = unit; op.iplo_size = sizeof(ipe); op.iplo_struct = &ipe; op.iplo_arg = 0; strncpy(op.iplo_name, name, sizeof(op.iplo_name)); bzero((char *)&ipe, sizeof(ipe)); bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr, sizeof(ipe.ipe_addr)); bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask, sizeof(ipe.ipe_mask)); if (opts & OPT_DEBUG) { printf("\t%s - ", inet_ntoa(ipe.ipe_addr.in4)); printf("%s\n", inet_ntoa(ipe.ipe_mask.in4)); } if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { if (!(opts & OPT_DONOTHING)) { - return ipf_perror_fd(pool_fd(), iocfunc, - "remove lookup hash node"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash node")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/remove_pool.c b/sbin/ipf/libipf/remove_pool.c index 157ab52179e0..1f09e529863e 100644 --- a/sbin/ipf/libipf/remove_pool.c +++ b/sbin/ipf/libipf/remove_pool.c @@ -1,45 +1,45 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_htable.h" int remove_pool(ip_pool_t *poolp, ioctlfunc_t iocfunc) { iplookupop_t op; ip_pool_t pool; if (pool_open() == -1) - return -1; + return(-1); op.iplo_type = IPLT_POOL; op.iplo_unit = poolp->ipo_unit; strncpy(op.iplo_name, poolp->ipo_name, sizeof(op.iplo_name)); op.iplo_size = sizeof(pool); op.iplo_struct = &pool; bzero((char *)&pool, sizeof(pool)); pool.ipo_unit = poolp->ipo_unit; strncpy(pool.ipo_name, poolp->ipo_name, sizeof(pool.ipo_name)); pool.ipo_flags = poolp->ipo_flags; if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "delete lookup pool"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup pool")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/remove_poolnode.c b/sbin/ipf/libipf/remove_poolnode.c index 78085c8041a4..bdbfc0f79163 100644 --- a/sbin/ipf/libipf/remove_poolnode.c +++ b/sbin/ipf/libipf/remove_poolnode.c @@ -1,51 +1,51 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include #include "ipf.h" #include "netinet/ip_lookup.h" #include "netinet/ip_pool.h" int remove_poolnode(int unit, char *name, ip_pool_node_t *node, ioctlfunc_t iocfunc) { ip_pool_node_t pn; iplookupop_t op; if (pool_open() == -1) - return -1; + return(-1); op.iplo_unit = unit; op.iplo_type = IPLT_POOL; op.iplo_arg = 0; strncpy(op.iplo_name, name, sizeof(op.iplo_name)); op.iplo_struct = &pn; op.iplo_size = sizeof(pn); bzero((char *)&pn, sizeof(pn)); bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr, sizeof(pn.ipn_addr)); bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask, sizeof(pn.ipn_mask)); pn.ipn_info = node->ipn_info; strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { if ((opts & OPT_DONOTHING) == 0) { - return ipf_perror_fd(pool_fd(), iocfunc, - "remove lookup pool node"); + return(ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup pool node")); } } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_execute.c b/sbin/ipf/libipf/save_execute.c index 0f46ec4ee3c7..21417145d569 100644 --- a/sbin/ipf/libipf/save_execute.c +++ b/sbin/ipf/libipf/save_execute.c @@ -1,76 +1,76 @@ #include "ipf.h" #include "ipmon.h" static void *execute_parse(char **); static void execute_destroy(void *); static int execute_send(void *, ipmon_msg_t *); static void execute_print(void *); typedef struct execute_opts_s { char *path; } execute_opts_t; ipmon_saver_t executesaver = { "execute", execute_destroy, NULL, /* dup */ NULL, /* match */ execute_parse, execute_print, execute_send }; static void * execute_parse(char **strings) { execute_opts_t *ctx; ctx = calloc(1, sizeof(*ctx)); if (ctx != NULL && strings[0] != NULL && strings[0][0] != '\0') { ctx->path = strdup(strings[0]); } else { free(ctx); - return NULL; + return(NULL); } - return ctx; + return(ctx); } static void execute_print(void *ctx) { execute_opts_t *exe = ctx; printf("%s", exe->path); } static void execute_destroy(void *ctx) { execute_opts_t *exe = ctx; if (exe != NULL) free(exe->path); free(exe); } static int execute_send(void *ctx, ipmon_msg_t *msg) { execute_opts_t *exe = ctx; FILE *fp; fp = popen(exe->path, "w"); if (fp != NULL) { fwrite(msg->imm_msg, msg->imm_msglen, 1, fp); pclose(fp); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_file.c b/sbin/ipf/libipf/save_file.c index 1ebcb45430af..54ecae2bf8ce 100644 --- a/sbin/ipf/libipf/save_file.c +++ b/sbin/ipf/libipf/save_file.c @@ -1,123 +1,123 @@ #include "ipf.h" #include "ipmon.h" static void *file_parse(char **); static void file_destroy(void *); static int file_send(void *, ipmon_msg_t *); static void file_print(void *); static int file_match(void *, void *); static void *file_dup(void *); typedef struct file_opts_s { FILE *fp; int raw; char *path; int ref; } file_opts_t; ipmon_saver_t filesaver = { "file", file_destroy, file_dup, file_match, file_parse, file_print, file_send }; static void * file_parse(char **strings) { file_opts_t *ctx; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) - return NULL; + return(NULL); if (strings[0] != NULL && strings[0][0] != '\0') { ctx->ref = 1; if (!strncmp(strings[0], "raw://", 6)) { ctx->raw = 1; ctx->path = strdup(strings[0] + 6); ctx->fp = fopen(ctx->path, "ab"); } else if (!strncmp(strings[0], "file://", 7)) { ctx->path = strdup(strings[0] + 7); ctx->fp = fopen(ctx->path, "a"); } else { free(ctx); ctx = NULL; } } else { free(ctx); ctx = NULL; } - return ctx; + return(ctx); } static int file_match(void *ctx1, void *ctx2) { file_opts_t *f1 = ctx1, *f2 = ctx2; if (f1->raw != f2->raw) - return 1; + return(1); if (strcmp(f1->path, f2->path)) - return 1; - return 0; + return(1); + return(0); } static void * file_dup(void *ctx) { file_opts_t *f = ctx; f->ref++; - return f; + return(f); } static void file_print(void *ctx) { file_opts_t *file = ctx; if (file->raw) printf("raw://"); else printf("file://"); printf("%s", file->path); } static void file_destroy(void *ctx) { file_opts_t *file = ctx; file->ref--; if (file->ref > 0) return; if (file->path != NULL) free(file->path); free(file); } static int file_send(void *ctx, ipmon_msg_t *msg) { file_opts_t *file = ctx; if (file->raw) { fwrite(msg->imm_data, msg->imm_dsize, 1, file->fp); } else { fprintf(file->fp, "%s", msg->imm_msg); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_nothing.c b/sbin/ipf/libipf/save_nothing.c index 6cb8948ab8ac..0a1d11e335f1 100644 --- a/sbin/ipf/libipf/save_nothing.c +++ b/sbin/ipf/libipf/save_nothing.c @@ -1,59 +1,59 @@ #include "ipf.h" #include "ipmon.h" static void *nothing_parse(char **); static void nothing_destroy(void *); static int nothing_send(void *, ipmon_msg_t *); typedef struct nothing_opts_s { FILE *fp; int raw; char *path; } nothing_opts_t; ipmon_saver_t nothingsaver = { "nothing", nothing_destroy, NULL, /* dup */ NULL, /* match */ nothing_parse, NULL, /* print */ nothing_send }; static void * nothing_parse(char **strings) { void *ctx; #if 0 strings = strings; /* gcc -Wextra */ #endif ctx = calloc(1, sizeof(void *)); - return ctx; + return(ctx); } static void nothing_destroy(void *ctx) { free(ctx); } static int nothing_send(void *ctx, ipmon_msg_t *msg) { #if 0 ctx = ctx; /* gcc -Wextra */ msg = msg; /* gcc -Wextra */ #endif /* * Do nothing */ - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_syslog.c b/sbin/ipf/libipf/save_syslog.c index ce75d428d186..88584c44dcd0 100644 --- a/sbin/ipf/libipf/save_syslog.c +++ b/sbin/ipf/libipf/save_syslog.c @@ -1,133 +1,133 @@ #include "ipf.h" #include "ipmon.h" #include static void *syslog_parse(char **); static void syslog_destroy(void *); static int syslog_send(void *, ipmon_msg_t *); static void syslog_print(void *); typedef struct syslog_opts_s { int facpri; int fac; int pri; } syslog_opts_t; ipmon_saver_t syslogsaver = { "syslog", syslog_destroy, NULL, /* dup */ NULL, /* match */ syslog_parse, syslog_print, syslog_send }; static void * syslog_parse(char **strings) { syslog_opts_t *ctx; char *str; char *s; ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) - return NULL; + return(NULL); ctx->facpri = -1; if (strings[0] != NULL && strings[0][0] != '\0') { str = strdup(*strings); if (str != NULL && *str != '\0') { int fac = -1, pri = -1; s = strchr(str, '.'); if (s != NULL) *s++ = '\0'; if (*str != '\0') { fac = fac_findname(str); if (fac == -1) { free(str); free(ctx); - return NULL; + return(NULL); } } if (s != NULL && *s != '\0') { pri = pri_findname(s); if (pri == -1) { free(str); free(ctx); - return NULL; + return(NULL); } } free(str); ctx->fac = fac; ctx->pri = pri; if (pri == -1) ctx->facpri = fac; else if (fac == -1) ctx->facpri = pri; else ctx->facpri = fac | pri; } else { if (str != NULL) free(str); free(ctx); ctx = NULL; } } - return ctx; + return(ctx); } static void syslog_print(void *ctx) { syslog_opts_t *sys = ctx; if (sys->facpri == -1) return; if (sys->fac == -1) { printf(".%s", pri_toname(sys->pri)); } else if (sys->pri == -1) { printf("%s.", fac_toname(sys->fac)); } else { printf("%s.%s", fac_toname(sys->facpri & LOG_FACMASK), pri_toname(sys->facpri & LOG_PRIMASK)); } } static void syslog_destroy(void *ctx) { free(ctx); } static int syslog_send(void *ctx, ipmon_msg_t *msg) { syslog_opts_t *sys = ctx; int facpri; if (sys->facpri == -1) { facpri = msg->imm_loglevel; } else { if (sys->pri == -1) { facpri = sys->fac | (msg->imm_loglevel & LOG_PRIMASK); } else if (sys->fac == -1) { facpri = sys->pri | (msg->imm_loglevel & LOG_FACMASK); } else { facpri = sys->facpri; } } syslog(facpri, "%s", msg->imm_msg); - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_v1trap.c b/sbin/ipf/libipf/save_v1trap.c index cbd555739462..c8390194d73e 100644 --- a/sbin/ipf/libipf/save_v1trap.c +++ b/sbin/ipf/libipf/save_v1trap.c @@ -1,443 +1,443 @@ #include "ipf.h" #include "netinet/ipl.h" #include "ipmon.h" #include #define IPF_ENTERPRISE 9932 /* * Enterprise number OID: * 1.3.6.1.4.1.9932 */ static u_char ipf_enterprise[] = { 6, 7, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c }; static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; static int writeint(u_char *, int); static int writelength(u_char *, u_int); static int maketrap_v1(char *, u_char *, int, u_char *, int, u_32_t, time_t); static void snmpv1_destroy(void *); static void *snmpv1_dup(void *); static int snmpv1_match(void *, void *); static void *snmpv1_parse(char **); static void snmpv1_print(void *); static int snmpv1_send(void *, ipmon_msg_t *); typedef struct snmpv1_opts_s { char *community; int fd; int v6; int ref; #ifdef USE_INET6 struct sockaddr_in6 sin6; #endif struct sockaddr_in sin; } snmpv1_opts_t; ipmon_saver_t snmpv1saver = { "snmpv1", snmpv1_destroy, snmpv1_dup, /* dup */ snmpv1_match, /* match */ snmpv1_parse, snmpv1_print, snmpv1_send }; static int snmpv1_match(void *ctx1, void *ctx2) { snmpv1_opts_t *s1 = ctx1, *s2 = ctx2; if (s1->v6 != s2->v6) - return 1; + return(1); if (strcmp(s1->community, s2->community)) - return 1; + return(1); #ifdef USE_INET6 if (s1->v6 == 1) { if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) - return 1; + return(1); } else #endif { if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) - return 1; + return(1); } - return 0; + return(0); } static void * snmpv1_dup(void *ctx) { snmpv1_opts_t *s = ctx; s->ref++; - return s; + return(s); } static void snmpv1_print(void *ctx) { snmpv1_opts_t *snmpv1 = ctx; printf("%s ", snmpv1->community); #ifdef USE_INET6 if (snmpv1->v6 == 1) { char buf[80]; printf("%s", inet_ntop(AF_INET6, &snmpv1->sin6.sin6_addr, buf, sizeof(snmpv1->sin6.sin6_addr))); } else #endif { printf("%s", inet_ntoa(snmpv1->sin.sin_addr)); } } static void * snmpv1_parse(char **strings) { snmpv1_opts_t *ctx; int result; char *str; char *s; if (strings[0] == NULL || strings[0][0] == '\0') - return NULL; + return(NULL); if (strchr(*strings, ' ') == NULL) - return NULL; + return(NULL); str = strdup(*strings); ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) - return NULL; + return(NULL); ctx->fd = -1; s = strchr(str, ' '); *s++ = '\0'; ctx->community = str; while (ISSPACE(*s)) s++; if (!*s) { free(str); free(ctx); - return NULL; + return(NULL); } #ifdef USE_INET6 if (strchr(s, ':') == NULL) { result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); if (result == 1) { ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin.sin_family = AF_INET; ctx->sin.sin_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, sizeof(ctx->sin)) != 0) { snmpv1_destroy(ctx); - return NULL; + return(NULL); } } } } else { result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); if (result == 1) { ctx->v6 = 1; ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin6.sin6_family = AF_INET6; ctx->sin6.sin6_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin6, sizeof(ctx->sin6)) != 0) { snmpv1_destroy(ctx); - return NULL; + return(NULL); } } } } #else result = inet_aton(s, &ctx->sin.sin_addr); if (result == 1) { ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin.sin_family = AF_INET; ctx->sin.sin_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, sizeof(ctx->sin)) != 0) { snmpv1_destroy(ctx); - return NULL; + return(NULL); } } } #endif if (result != 1) { free(str); free(ctx); - return NULL; + return(NULL); } ctx->ref = 1; - return ctx; + return(ctx); } static void snmpv1_destroy(void *ctx) { snmpv1_opts_t *v1 = ctx; v1->ref--; if (v1->ref > 0) return; if (v1->community) free(v1->community); if (v1->fd >= 0) close(v1->fd); free(v1); } static int snmpv1_send(void *ctx, ipmon_msg_t *msg) { snmpv1_opts_t *v1 = ctx; - return sendtrap_v1_0(v1->fd, v1->community, - msg->imm_msg, msg->imm_msglen, msg->imm_when); + return(sendtrap_v1_0(v1->fd, v1->community, + msg->imm_msg, msg->imm_msglen, msg->imm_when)); } static char def_community[] = "public"; /* ublic */ static int writelength(u_char *buffer, u_int value) { u_int n = htonl(value); int len; if (value < 128) { *buffer = value; - return 1; + return(1); } if (value > 0xffffff) len = 4; else if (value > 0xffff) len = 3; else if (value > 0xff) len = 2; else len = 1; *buffer = 0x80 | len; bcopy((u_char *)&n + 4 - len, buffer + 1, len); - return len + 1; + return(len + 1); } static int writeint(u_char *buffer, int value) { u_char *s = buffer; u_int n = value; if (value == 0) { *buffer = 0; - return 1; + return(1); } if (n > 4194304) { *s++ = 0x80 | (n / 4194304); n -= 4194304 * (n / 4194304); } if (n > 32768) { *s++ = 0x80 | (n / 32768); n -= 32768 * (n / 327678); } if (n > 128) { *s++ = 0x80 | (n / 128); n -= (n / 128) * 128; } *s++ = (u_char)n; - return s - buffer; + return(s - buffer); } /* * First style of traps is: * 1.3.6.1.4.1.9932.1.1 */ static int maketrap_v1(char *community, u_char *buffer, int bufsize, u_char *msg, int msglen, u_32_t ipaddr, time_t when) { u_char *s = buffer, *t, *pdulen, *varlen; int basesize = 73; u_short len; int trapmsglen; int pdulensz; int varlensz; int baselensz; int n; if (community == NULL || *community == '\0') community = def_community; basesize += strlen(community) + msglen; if (basesize + 8 > bufsize) - return 0; + return(0); memset(buffer, 0xff, bufsize); *s++ = 0x30; /* Sequence */ if (basesize - 1 >= 128) { baselensz = 2; basesize++; } else { baselensz = 1; } s += baselensz; *s++ = 0x02; /* Integer32 */ *s++ = 0x01; /* length 1 */ *s++ = 0x00; /* version 1 */ *s++ = 0x04; /* octet string */ *s++ = strlen(community); /* length of "public" */ bcopy(community, s, s[-1]); s += s[-1]; *s++ = 0xA4; /* PDU(4) */ pdulen = s++; if (basesize - (s - buffer) >= 128) { pdulensz = 2; basesize++; s++; } else { pdulensz = 1; } /* enterprise */ bcopy(ipf_enterprise, s, sizeof(ipf_enterprise)); s += sizeof(ipf_enterprise); /* Agent address */ *s++ = 0x40; *s++ = 0x4; bcopy(&ipaddr, s, 4); s += 4; /* Generic Trap code */ *s++ = 0x2; n = writeint(s + 1, 6); if (n == 0) - return 0; + return(0); *s = n; s += n + 1; /* Specific Trap code */ *s++ = 0x2; n = writeint(s + 1, 0); if (n == 0) - return 0; + return(0); *s = n; s += n + 1; /* Time stamp */ *s++ = 0x43; /* TimeTicks */ *s++ = 0x04; /* TimeTicks */ s[0] = when >> 24; s[1] = when >> 16; s[2] = when >> 8; s[3] = when & 0xff; s += 4; /* * The trap0 message is "ipfilter_version" followed by the message */ *s++ = 0x30; varlen = s; if (basesize - (s - buffer) >= 128) { varlensz = 2; basesize++; } else { varlensz = 1; } s += varlensz; *s++ = 0x30; t = s + 1; bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); t += sizeof(ipf_trap0_1); *t++ = 0x2; /* Integer */ n = writeint(t + 1, IPFILTER_VERSION); *t = n; t += n + 1; len = t - s - 1; writelength(s, len); s = t; *s++ = 0x30; if (basesize - (s - buffer) >= 128) { trapmsglen = 2; basesize++; } else { trapmsglen = 1; } t = s + trapmsglen; bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); t += sizeof(ipf_trap0_2); *t++ = 0x4; /* Octet string */ n = writelength(t, msglen); t += n; bcopy(msg, t, msglen); t += msglen; len = t - s - trapmsglen; writelength(s, len); len = t - varlen - varlensz; writelength(varlen, len); /* pdu length */ len = t - pdulen - pdulensz; writelength(pdulen, len); /* pdu length */ len = t - buffer - baselensz - 1; writelength(buffer + 1, len); /* length of trap */ - return t - buffer; + return(t - buffer); } int sendtrap_v1_0(int fd, char *community, char *msg, int msglen, time_t when) { u_char buffer[1500]; int n; n = maketrap_v1(community, buffer, sizeof(buffer), (u_char *)msg, msglen, 0, when); if (n > 0) { - return send(fd, buffer, n, 0); + return(send(fd, buffer, n, 0)); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/save_v2trap.c b/sbin/ipf/libipf/save_v2trap.c index 4572d5c267ed..4843c7134508 100644 --- a/sbin/ipf/libipf/save_v2trap.c +++ b/sbin/ipf/libipf/save_v2trap.c @@ -1,444 +1,444 @@ #include "ipf.h" #include "netinet/ipl.h" #include "ipmon.h" #include static u_char sysuptime[] = { 6, 8, 0x2b, 6, 1, 2, 1, 1, 3, 0 }; /* * Enterprise number OID: * 1.3.6.1.4.1.9932 */ static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; static int writeint(u_char *, int); static int writelength(u_char *, u_int); static int maketrap_v2(char *, u_char *, int, u_char *, int); static void snmpv2_destroy(void *); static void *snmpv2_dup(void *); static int snmpv2_match(void *, void *); static void *snmpv2_parse(char **); static void snmpv2_print(void *); static int snmpv2_send(void *, ipmon_msg_t *); int sendtrap_v2_0(int, char *, char *, int); static char def_community[] = "public"; /* ublic */ typedef struct snmpv2_opts_s { char *community; char *server; int fd; int v6; int ref; #ifdef USE_INET6 struct sockaddr_in6 sin6; #endif struct sockaddr_in sin; } snmpv2_opts_t; ipmon_saver_t snmpv2saver = { "snmpv2", snmpv2_destroy, snmpv2_dup, /* dup */ snmpv2_match, /* match */ snmpv2_parse, snmpv2_print, snmpv2_send }; static int snmpv2_match(void *ctx1, void *ctx2) { snmpv2_opts_t *s1 = ctx1, *s2 = ctx2; if (s1->v6 != s2->v6) - return 1; + return(1); if (strcmp(s1->community, s2->community)) - return 1; + return(1); #ifdef USE_INET6 if (s1->v6 == 1) { if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) - return 1; + return(1); } else #endif { if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) - return 1; + return(1); } - return 0; + return(0); } static void * snmpv2_dup(void *ctx) { snmpv2_opts_t *s = ctx; s->ref++; - return s; + return(s); } static void snmpv2_print(void *ctx) { snmpv2_opts_t *snmpv2 = ctx; printf("%s ", snmpv2->community); #ifdef USE_INET6 if (snmpv2->v6 == 1) { char buf[80]; printf("%s", inet_ntop(AF_INET6, &snmpv2->sin6.sin6_addr, buf, sizeof(snmpv2->sin6.sin6_addr))); } else #endif { printf("%s", inet_ntoa(snmpv2->sin.sin_addr)); } } static void * snmpv2_parse(char **strings) { snmpv2_opts_t *ctx; int result; char *str; char *s; if (strings[0] == NULL || strings[0][0] == '\0') - return NULL; + return(NULL); if (strchr(*strings, ' ') == NULL) - return NULL; + return(NULL); str = strdup(*strings); ctx = calloc(1, sizeof(*ctx)); if (ctx == NULL) { free(str); - return NULL; + return(NULL); } ctx->fd = -1; s = strchr(str, ' '); *s++ = '\0'; ctx->community = str; while (ISSPACE(*s)) s++; if (!*s) { free(str); free(ctx); - return NULL; + return(NULL); } #ifdef USE_INET6 if (strchr(s, ':') == NULL) { result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); if (result == 1) { ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin.sin_family = AF_INET; ctx->sin.sin_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, sizeof(ctx->sin)) != 0) { snmpv2_destroy(ctx); - return NULL; + return(NULL); } } } } else { result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); if (result == 1) { ctx->v6 = 1; ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin6.sin6_family = AF_INET6; ctx->sin6.sin6_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin6, sizeof(ctx->sin6)) != 0) { snmpv2_destroy(ctx); - return NULL; + return(NULL); } } } } #else result = inet_aton(s, &ctx->sin.sin_addr); if (result == 1) { ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); if (ctx->fd >= 0) { ctx->sin.sin_family = AF_INET; ctx->sin.sin_port = htons(162); if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, sizeof(ctx->sin)) != 0) { snmpv2_destroy(ctx); - return NULL; + return(NULL); } } } #endif if (result != 1) { free(str); free(ctx); - return NULL; + return(NULL); } ctx->ref = 1; - return ctx; + return(ctx); } static void snmpv2_destroy(void *ctx) { snmpv2_opts_t *v2 = ctx; v2->ref--; if (v2->ref > 0) return; if (v2->community) free(v2->community); if (v2->fd >= 0) close(v2->fd); free(v2); } static int snmpv2_send(void *ctx, ipmon_msg_t *msg) { snmpv2_opts_t *v2 = ctx; - return sendtrap_v2_0(v2->fd, v2->community, - msg->imm_msg, msg->imm_msglen); + return(sendtrap_v2_0(v2->fd, v2->community, + msg->imm_msg, msg->imm_msglen)); } static int writelength(u_char *buffer, u_int value) { u_int n = htonl(value); int len; if (value < 128) { *buffer = value; - return 1; + return(1); } if (value > 0xffffff) len = 4; else if (value > 0xffff) len = 3; else if (value > 0xff) len = 2; else len = 1; *buffer = 0x80 | len; bcopy((u_char *)&n + 4 - len, buffer + 1, len); - return len + 1; + return(len + 1); } static int writeint(u_char *buffer, int value) { u_char *s = buffer; u_int n = value; if (value == 0) { *buffer = 0; - return 1; + return(1); } if (n > 4194304) { *s++ = 0x80 | (n / 4194304); n -= 4194304 * (n / 4194304); } if (n > 32768) { *s++ = 0x80 | (n / 32768); n -= 32768 * (n / 327678); } if (n > 128) { *s++ = 0x80 | (n / 128); n -= (n / 128) * 128; } *s++ = (u_char)n; - return s - buffer; + return(s - buffer); } /* * First style of traps is: * 1.3.6.1.4.1.9932.1.1 */ static int maketrap_v2(char *community, u_char *buffer, int bufsize, u_char *msg, int msglen) { u_char *s = buffer, *t, *pdulen; u_char *varlen; int basesize = 77; u_short len; int trapmsglen; int pdulensz; int varlensz; int baselensz; int n; if (community == NULL || *community == '\0') community = def_community; basesize += strlen(community) + msglen; if (basesize + 8 > bufsize) - return 0; + return(0); memset(buffer, 0xff, bufsize); *s++ = 0x30; /* Sequence */ if (basesize - 1 >= 128) { baselensz = 2; basesize++; } else { baselensz = 1; } s += baselensz; *s++ = 0x02; /* Integer32 */ *s++ = 0x01; /* length 1 */ *s++ = 0x01; /* version 2 */ *s++ = 0x04; /* octet string */ *s++ = strlen(community); /* length of "public" */ bcopy(community, s, s[-1]); s += s[-1]; *s++ = 0xA7; /* PDU(7) */ pdulen = s++; if (basesize - (s - buffer) >= 128) { pdulensz = 2; basesize++; s++; } else { pdulensz = 1; } /* request id */ *s++ = 0x2; /* integer */ *s++ = 0x4; /* len 4 */ *s++ = 0x0; /* noError */ *s++ = 0x0; /* noError */ *s++ = 0x0; /* noError */ *s++ = 0x0; /* noError */ /* error status */ *s++ = 0x2; /* integer */ *s++ = 0x1; /* len 1 */ *s++ = 0x0; /* noError */ /* error-index */ *s++ = 0x2; /* integer */ *s++ = 0x1; /* len 1 */ *s++ = 0x0; /* noError */ *s++ = 0x30; /* sequence */ varlen = s++; if (basesize - (s - buffer) >= 128) { varlensz = 2; basesize++; s++; } else { varlensz = 1; } *s++ = 0x30; /* sequence */ *s++ = sizeof(sysuptime) + 6; bcopy(sysuptime, s, sizeof(sysuptime)); s += sizeof(sysuptime); *s++ = 0x43; /* Timestamp */ *s++ = 0x04; /* TimeTicks */ *s++ = 0x0; *s++ = 0x0; *s++ = 0x0; *s++ = 0x0; *s++ = 0x30; t = s + 1; bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); t += sizeof(ipf_trap0_1); *t++ = 0x2; /* Integer */ n = writeint(t + 1, IPFILTER_VERSION); *t = n; t += n + 1; len = t - s - 1; writelength(s, len); s = t; *s++ = 0x30; if (msglen < 128) { if (msglen + 1 + 1 + sizeof(ipf_trap0_2) >= 128) trapmsglen = 2; else trapmsglen = 1; } else { if (msglen + 2 + 1 + sizeof(ipf_trap0_2) >= 128) trapmsglen = 2; else trapmsglen = 1; } t = s + trapmsglen; bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); t += sizeof(ipf_trap0_2); *t++ = 0x4; /* Octet string */ n = writelength(t, msglen); t += n; bcopy(msg, t, msglen); t += msglen; len = t - s - trapmsglen; writelength(s, len); len = t - varlen - varlensz; writelength(varlen, len); /* pdu length */ len = t - pdulen - pdulensz; writelength(pdulen, len); /* pdu length */ len = t - buffer - baselensz - 1; writelength(buffer + 1, len); /* length of trap */ - return t - buffer; + return(t - buffer); } int sendtrap_v2_0(int fd, char *community, char *msg, int msglen) { u_char buffer[1500]; int n; n = maketrap_v2(community, buffer, sizeof(buffer), (u_char *)msg, msglen); if (n > 0) { - return send(fd, buffer, n, 0); + return(send(fd, buffer, n, 0)); } - return 0; + return(0); } diff --git a/sbin/ipf/libipf/tcp_flags.c b/sbin/ipf/libipf/tcp_flags.c index 9dfe96d17fe8..9e371b628142 100644 --- a/sbin/ipf/libipf/tcp_flags.c +++ b/sbin/ipf/libipf/tcp_flags.c @@ -1,47 +1,47 @@ /* $FreeBSD$ */ /* * Copyright (C) 2000-2004 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id: tcp_flags.c,v 1.8.2.1 2006/06/16 17:21:17 darrenr Exp $ */ #include "ipf.h" extern char flagset[]; extern u_char flags[]; u_char tcp_flags(char *flgs, u_char *mask, int linenum) { u_char tcpf = 0, tcpfm = 0; char *s; s = strchr(flgs, '/'); if (s) *s++ = '\0'; if (*flgs == '0') { tcpf = strtol(flgs, NULL, 0); } else { tcpf = tcpflags(flgs); } if (s != NULL) { if (*s == '0') tcpfm = strtol(s, NULL, 0); else tcpfm = tcpflags(s); } if (!tcpfm) { if (tcpf == TH_SYN) tcpfm = 0xff & ~(TH_ECN|TH_CWR); else tcpfm = 0xff & ~(TH_ECN); } *mask = tcpfm; - return tcpf; + return(tcpf); } diff --git a/sbin/ipf/libipf/tcpflags.c b/sbin/ipf/libipf/tcpflags.c index 86f7631abf80..efb991299961 100644 --- a/sbin/ipf/libipf/tcpflags.c +++ b/sbin/ipf/libipf/tcpflags.c @@ -1,44 +1,44 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" /* * ECN is a new addition to TCP - RFC 2481 */ #ifndef TH_ECN # define TH_ECN 0x40 #endif #ifndef TH_CWR # define TH_CWR 0x80 #endif extern char flagset[]; extern u_char flags[]; u_char tcpflags(char *flgs) { u_char tcpf = 0; char *s, *t; for (s = flgs; *s; s++) { if (*s == 'W') tcpf |= TH_CWR; else { if (!(t = strchr(flagset, *s))) { - return 0; + return(0); } tcpf |= flags[t - flagset]; } } - return tcpf; + return(tcpf); } diff --git a/sbin/ipf/libipf/v6optvalue.c b/sbin/ipf/libipf/v6optvalue.c index 39757bc849b1..3578394317e1 100644 --- a/sbin/ipf/libipf/v6optvalue.c +++ b/sbin/ipf/libipf/v6optvalue.c @@ -1,37 +1,37 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include "ipf.h" u_32_t getv6optbyname(char *optname) { #ifdef USE_INET6 struct ipopt_names *io; for (io = v6ionames; io->on_name; io++) if (!strcasecmp(optname, io->on_name)) - return io->on_bit; + return(io->on_bit); #endif - return -1; + return(-1); } u_32_t getv6optbyvalue(int optval) { #ifdef USE_INET6 struct ipopt_names *io; for (io = v6ionames; io->on_name; io++) if (io->on_value == optval) - return io->on_bit; + return(io->on_bit); #endif - return -1; + return(-1); } diff --git a/sbin/ipf/libipf/var.c b/sbin/ipf/libipf/var.c index d864117e5df9..769b8fc06673 100644 --- a/sbin/ipf/libipf/var.c +++ b/sbin/ipf/libipf/var.c @@ -1,173 +1,173 @@ /* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. * * $Id$ */ #include #include "ipf.h" typedef struct variable { struct variable *v_next; char *v_name; char *v_value; } variable_t; static variable_t *vtop = NULL; static variable_t *find_var(char *); static char *expand_string(char *, int); static variable_t *find_var(name) char *name; { variable_t *v; for (v = vtop; v != NULL; v = v->v_next) if (!strcmp(name, v->v_name)) - return v; - return NULL; + return(v); + return(NULL); } char *get_variable(char *string, char **after, int line) { char c, *s, *t, *value; variable_t *v; s = string; if (*s == '{') { s++; for (t = s; *t != '\0'; t++) if (*t == '}') break; if (*t == '\0') { fprintf(stderr, "%d: { without }\n", line); - return NULL; + return(NULL); } } else if (ISALPHA(*s)) { for (t = s + 1; *t != '\0'; t++) if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) break; } else { fprintf(stderr, "%d: variables cannot start with '%c'\n", line, *s); - return NULL; + return(NULL); } if (after != NULL) *after = t; c = *t; *t = '\0'; v = find_var(s); *t = c; if (v == NULL) { fprintf(stderr, "%d: unknown variable '%s'\n", line, s); - return NULL; + return(NULL); } s = strdup(v->v_value); value = expand_string(s, line); if (value != s) free(s); - return value; + return(value); } static char *expand_string(char *oldstring, int line) { char c, *s, *p1, *p2, *p3, *newstring, *value; int len; p3 = NULL; newstring = oldstring; for (s = oldstring; *s != '\0'; s++) if (*s == '$') { *s = '\0'; s++; switch (*s) { case '$' : bcopy(s, s - 1, strlen(s)); break; default : c = *s; if (c == '\0') - return newstring; + return(newstring); value = get_variable(s, &p3, line); if (value == NULL) - return NULL; + return(NULL); p2 = expand_string(value, line); if (p2 == NULL) - return NULL; + return(NULL); len = strlen(newstring) + strlen(p2); if (p3 != NULL) { if (c == '{' && *p3 == '}') p3++; len += strlen(p3); } p1 = malloc(len + 1); if (p1 == NULL) - return NULL; + return(NULL); *(s - 1) = '\0'; strcpy(p1, newstring); strcat(p1, p2); if (p3 != NULL) strcat(p1, p3); s = p1 + len - strlen(p3) - 1; if (newstring != oldstring) free(newstring); newstring = p1; break; } } - return newstring; + return(newstring); } void set_variable(char *name, char *value) { variable_t *v; int len; if (name == NULL || value == NULL || *name == '\0') return; v = find_var(name); if (v != NULL) { free(v->v_value); v->v_value = strdup(value); return; } len = strlen(value); if ((*value == '"' && value[len - 1] == '"') || (*value == '\'' && value[len - 1] == '\'')) { value[len - 1] = '\0'; value++; len -=2; } v = (variable_t *)malloc(sizeof(*v)); if (v == NULL) return; v->v_name = strdup(name); v->v_value = strdup(value); v->v_next = vtop; vtop = v; } diff --git a/sbin/ipf/libipf/vtof.c b/sbin/ipf/libipf/vtof.c index 2d624ac64d45..0b0b767b94c1 100644 --- a/sbin/ipf/libipf/vtof.c +++ b/sbin/ipf/libipf/vtof.c @@ -1,15 +1,15 @@ #include "ipf.h" int vtof(int version) { #ifdef USE_INET6 if (version == 6) - return AF_INET6; + return(AF_INET6); #endif if (version == 4) - return AF_INET; + return(AF_INET); if (version == 0) - return AF_UNSPEC; - return -1; + return(AF_UNSPEC); + return(-1); }