diff options
Diffstat (limited to 'tools/ippool_y.y')
-rw-r--r-- | tools/ippool_y.y | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/tools/ippool_y.y b/tools/ippool_y.y new file mode 100644 index 0000000..4aa5108 --- /dev/null +++ b/tools/ippool_y.y @@ -0,0 +1,520 @@ +/* + * Copyright (C) 2001-2006 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +%{ +#include <sys/types.h> +#include <sys/time.h> +#include <sys/param.h> +#include <sys/socket.h> +#if defined(BSD) && (BSD >= 199306) +# include <sys/cdefs.h> +#endif +#include <sys/ioctl.h> + +#include <net/if.h> +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#include <netinet/in.h> + +#include <arpa/inet.h> + +#include <stdio.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include <ctype.h> +#include <unistd.h> + +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" +#include "netinet/ip_htable.h" +#include "ippool_l.h" +#include "kmem.h" + +#define YYDEBUG 1 +#define YYSTACKSIZE 0x00ffffff + +extern int yyparse __P((void)); +extern int yydebug; +extern FILE *yyin; + +static iphtable_t ipht; +static iphtent_t iphte; +static ip_pool_t iplo; +static ioctlfunc_t poolioctl = NULL; +static char poolname[FR_GROUPLEN]; + +static iphtent_t *add_htablehosts __P((char *)); +static ip_pool_node_t *add_poolhosts __P((char *)); + +%} + +%union { + char *str; + u_32_t num; + struct in_addr addr; + struct alist_s *alist; + struct in_addr adrmsk[2]; + iphtent_t *ipe; + ip_pool_node_t *ipp; + union i6addr ip6; +} + +%token <num> YY_NUMBER YY_HEX +%token <str> YY_STR +%token YY_COMMENT +%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT +%token YY_RANGE_OUT YY_RANGE_IN +%token <ip6> YY_IPV6 + +%token IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT +%token IPT_TABLE IPT_GROUPMAP IPT_HASH +%token IPT_ROLE IPT_TYPE IPT_TREE +%token IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME +%type <num> role table inout +%type <ipp> ipftree range addrlist +%type <adrmsk> addrmask +%type <ipe> ipfgroup ipfhash hashlist hashentry +%type <ipe> groupentry setgrouplist grouplist +%type <addr> ipaddr mask ipv4 +%type <str> number setgroup + +%% +file: line + | assign + | file line + | file assign + ; + +line: table role ipftree eol { iplo.ipo_unit = $2; + iplo.ipo_list = $3; + load_pool(&iplo, poolioctl); + resetlexer(); + } + | table role ipfhash eol { ipht.iph_unit = $2; + ipht.iph_type = IPHASH_LOOKUP; + load_hash(&ipht, $3, poolioctl); + resetlexer(); + } + | groupmap role number ipfgroup eol + { ipht.iph_unit = $2; + strncpy(ipht.iph_name, $3, + sizeof(ipht.iph_name)); + ipht.iph_type = IPHASH_GROUPMAP; + load_hash(&ipht, $4, poolioctl); + resetlexer(); + } + | YY_COMMENT + ; + +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)); + *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 '=' IPT_IPF { $$ = IPL_LOGIPF; } + | IPT_ROLE '=' IPT_NAT { $$ = IPL_LOGNAT; } + | IPT_ROLE '=' IPT_AUTH { $$ = IPL_LOGAUTH; } + | IPT_ROLE '=' IPT_COUNT { $$ = IPL_LOGCOUNT; } + ; + +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; + } + | hashopts start setgrouplist end { $$ = $3; } + ; + +number: IPT_NUM '=' YY_NUMBER { sprintf(poolname, "%u", $3); + $$ = poolname; + } + | IPT_NAME '=' YY_STR { $$ = $3; } + | { $$ = ""; } + ; + +setgroup: + IPT_GROUP '=' YY_STR { char tmp[FR_GROUPLEN+1]; + strncpy(tmp, $3, FR_GROUPLEN); + $$ = strdup(tmp); + } + | IPT_GROUP '=' YY_NUMBER { char tmp[FR_GROUPLEN+1]; + sprintf(tmp, "%u", $3); + $$ = strdup(tmp); + } + ; + +hashopts: + | size + | seed + | size seed + ; + +addrlist: + next { $$ = NULL; } + | range next addrlist { $1->ipn_next = $3; $$ = $1; } + | range next { $$ = $1; } + ; + +grouplist: + next { $$ = NULL; } + | groupentry next grouplist { $$ = $1; $1->ipe_next = $3; } + | addrmask next grouplist { $$ = calloc(1, sizeof(iphtent_t)); + bcopy((char *)&($1[0]), + (char *)&($$->ipe_addr), + sizeof($$->ipe_addr)); + bcopy((char *)&($1[1]), + (char *)&($$->ipe_mask), + sizeof($$->ipe_mask)); + $$->ipe_next = $3; + } + | groupentry next { $$ = $1; } + | addrmask next { $$ = calloc(1, sizeof(iphtent_t)); + bcopy((char *)&($1[0]), + (char *)&($$->ipe_addr), + sizeof($$->ipe_addr)); + bcopy((char *)&($1[1]), + (char *)&($$->ipe_mask), + sizeof($$->ipe_mask)); + } + ; + +setgrouplist: + next { $$ = NULL; } + | groupentry next { $$ = $1; } + | groupentry next setgrouplist { $1->ipe_next = $3; $$ = $1; } + ; + +groupentry: + addrmask ',' setgroup { $$ = calloc(1, sizeof(iphtent_t)); + bcopy((char *)&($1[0]), + (char *)&($$->ipe_addr), + sizeof($$->ipe_addr)); + bcopy((char *)&($1[1]), + (char *)&($$->ipe_mask), + sizeof($$->ipe_mask)); + strncpy($$->ipe_group, $3, + FR_GROUPLEN); + free($3); + } + | YY_STR { $$ = add_htablehosts($1); } + ; + +range: addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 0; + $$->ipn_addr.adf_len = sizeof($$->ipn_addr); + $$->ipn_addr.adf_addr.in4.s_addr = $1[0].s_addr; + $$->ipn_mask.adf_len = sizeof($$->ipn_mask); + $$->ipn_mask.adf_addr.in4.s_addr = $1[1].s_addr; + } + | '!' addrmask { $$ = calloc(1, sizeof(*$$)); + $$->ipn_info = 1; + $$->ipn_addr.adf_len = sizeof($$->ipn_addr); + $$->ipn_addr.adf_addr.in4.s_addr = $2[0].s_addr; + $$->ipn_mask.adf_len = sizeof($$->ipn_mask); + $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr; + } + | YY_STR { $$ = add_poolhosts($1); } + +hashlist: + next { $$ = NULL; } + | hashentry next { $$ = $1; } + | hashentry next hashlist { $1->ipe_next = $3; $$ = $1; } + ; + +hashentry: + addrmask { $$ = calloc(1, sizeof(iphtent_t)); + bcopy((char *)&($1[0]), + (char *)&($$->ipe_addr), + sizeof($$->ipe_addr)); + bcopy((char *)&($1[1]), + (char *)&($$->ipe_mask), + sizeof($$->ipe_mask)); + } + | YY_STR { $$ = add_htablehosts($1); } + ; + +addrmask: + ipaddr '/' mask { $$[0] = $1; $$[1].s_addr = $3.s_addr; + yyexpectaddr = 0; + } + | ipaddr { $$[0] = $1; $$[1].s_addr = 0xffffffff; + yyexpectaddr = 0; + } + ; + +ipaddr: ipv4 { $$ = $1; } + | YY_NUMBER { $$.s_addr = htonl($1); } + ; + +mask: YY_NUMBER { ntomask(4, $1, (u_32_t *)&$$.s_addr); } + | ipv4 { $$ = $1; } + ; + +start: '{' { yyexpectaddr = 1; } + ; + +end: '}' { yyexpectaddr = 0; } + ; + +next: ';' { yyexpectaddr = 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; + } + $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; + $$.s_addr = htonl($$.s_addr); + } + ; +%% +static wordtab_t yywords[] = { + { "auth", IPT_AUTH }, + { "count", IPT_COUNT }, + { "group", IPT_GROUP }, + { "group-map", IPT_GROUPMAP }, + { "hash", IPT_HASH }, + { "in", IPT_IN }, + { "ipf", IPT_IPF }, + { "name", IPT_NAME }, + { "nat", IPT_NAT }, + { "number", IPT_NUM }, + { "out", IPT_OUT }, + { "role", IPT_ROLE }, + { "seed", IPT_SEED }, + { "size", IPT_SIZE }, + { "table", IPT_TABLE }, + { "tree", IPT_TREE }, + { "type", IPT_TYPE }, + { NULL, 0 } +}; + + +int ippool_parsefile(fd, filename, iocfunc) +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; + } + } else + fp = stdin; + + while (ippool_parsesome(fd, fp, iocfunc) == 1) + ; + if (fp != NULL) + fclose(fp); + return 0; +} + + +int ippool_parsesome(fd, fp, iocfunc) +int fd; +FILE *fp; +ioctlfunc_t iocfunc; +{ + char *s; + int i; + + poolioctl = iocfunc; + + if (feof(fp)) + return 0; + i = fgetc(fp); + if (i == EOF) + return 0; + if (ungetc(i, fp) == EOF) + return 0; + if (feof(fp)) + return 0; + s = getenv("YYDEBUG"); + if (s) + yydebug = atoi(s); + else + yydebug = 0; + + yyin = fp; + yyparse(); + return 1; +} + + +static iphtent_t * +add_htablehosts(url) +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; + + if (gethost(url, &hlist->al_addr) == -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; + + bcopy((char *)&a->al_addr, (char *)&h->ipe_addr, + sizeof(h->ipe_addr)); + bcopy((char *)&a->al_mask, (char *)&h->ipe_mask, + sizeof(h->ipe_mask)); + + if (hbot != NULL) + hbot->ipe_next = h; + else + htop = h; + hbot = h; + } + + alist_free(hlist); + + return htop; +} + + +static ip_pool_node_t * +add_poolhosts(url) +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; + + if (gethost(url, &hlist->al_addr) == -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_addr.adf_len = 8; + p->ipn_mask.adf_len = 8; + + p->ipn_info = a->al_not; + + bcopy((char *)&a->al_addr, (char *)&p->ipn_addr.adf_addr, + sizeof(p->ipn_addr.adf_addr)); + bcopy((char *)&a->al_mask, (char *)&p->ipn_mask.adf_addr, + sizeof(p->ipn_mask.adf_addr)); + + if (pbot != NULL) + pbot->ipn_next = p; + else + ptop = p; + pbot = p; + } + + alist_free(hlist); + + return ptop; +} |