diff options
Diffstat (limited to 'contrib/ipfilter/tools/ipscan_y.y')
-rw-r--r-- | contrib/ipfilter/tools/ipscan_y.y | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/contrib/ipfilter/tools/ipscan_y.y b/contrib/ipfilter/tools/ipscan_y.y new file mode 100644 index 0000000..64cbb6d --- /dev/null +++ b/contrib/ipfilter/tools/ipscan_y.y @@ -0,0 +1,565 @@ +/* $NetBSD$ */ + +%{ +#include <sys/types.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "opts.h" +#include "kmem.h" +#include "ipscan_l.h" +#include "netinet/ip_scan.h" + +#define YYDEBUG 1 + +extern char *optarg; +extern void yyerror __P((char *)); +extern int yyparse __P((void)); +extern int yylex __P((void)); +extern int yydebug; +extern FILE *yyin; +extern int yylineNum; +extern void printbuf __P((char *, int, int)); + + +void printent __P((ipscan_t *)); +void showlist __P((void)); +int getportnum __P((char *)); +struct in_addr gethostip __P((char *)); +struct in_addr combine __P((int, int, int, int)); +char **makepair __P((char *, char *)); +void addtag __P((char *, char **, char **, struct action *)); +int cram __P((char *, char *)); +void usage __P((char *)); +int main __P((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 <str> tag +%type <act> action redirect result +%type <ipa> ipaddr +%type <num> portnum +%type <astr> matchup onehalf twohalves + +%token <num> YY_NUMBER YY_HEX +%token <str> YY_STR +%token YY_COMMENT +%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT +%token YY_RANGE_OUT YY_RANGE_IN +%token <ip6> YY_IPV6 +%token 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); + } + ; + +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(dst, src) +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; +} + + +void printent(isc) +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(tstr, cp, sp, act) +char *tstr; +char **cp, **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(s1, s2) +char *s1, *s2; +{ + char **a; + + a = malloc(sizeof(char *) * 2); + a[0] = s1; + a[1] = s2; + return a; +} + + +struct in_addr combine(a1, a2, a3, a4) +int a1, a2, a3, 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; +} + + +struct in_addr gethostip(host) +char *host; +{ + struct hostent *hp; + struct in_addr in; + + in.s_addr = 0; + + hp = gethostbyname(host); + if (!hp) + return in; + bcopy(hp->h_addr, (char *)&in, sizeof(in)); + return in; +} + + +int getportnum(port) +char *port; +{ + struct servent *s; + + s = getservbyname(port, "tcp"); + if (s == NULL) + return -1; + return s->s_port; +} + + +void showlist() +{ + 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(prog) +char *prog; +{ + fprintf(stderr, "Usage:\t%s [-dnrv] -f <filename>\n", prog); + fprintf(stderr, "\t%s [-dlv]\n", prog); + exit(1); +} + + +int main(argc, argv) +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); +} |