Home | History | Annotate | Line # | Download | only in tools
      1 /*	$NetBSD: ippool_y.y,v 1.1.1.2 2012/07/22 13:44:58 darrenr Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2012 by Darren Reed.
      5  *
      6  * See the IPFILTER.LICENCE file for details on licencing.
      7  */
      8 %{
      9 #include <sys/types.h>
     10 #include <sys/time.h>
     11 #include <sys/param.h>
     12 #include <sys/socket.h>
     13 #if defined(BSD) && (BSD >= 199306)
     14 # include <sys/cdefs.h>
     15 #endif
     16 #include <sys/ioctl.h>
     17 
     18 #include <net/if.h>
     19 #if __FreeBSD_version >= 300000
     20 # include <net/if_var.h>
     21 #endif
     22 #include <netinet/in.h>
     23 
     24 #include <arpa/inet.h>
     25 
     26 #include <stdio.h>
     27 #include <fcntl.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include <netdb.h>
     31 #include <ctype.h>
     32 #include <unistd.h>
     33 
     34 #include "ipf.h"
     35 #include "netinet/ip_lookup.h"
     36 #include "netinet/ip_pool.h"
     37 #include "netinet/ip_htable.h"
     38 #include "netinet/ip_dstlist.h"
     39 #include "ippool_l.h"
     40 #include "kmem.h"
     41 
     42 #define	YYDEBUG	1
     43 #define	YYSTACKSIZE	0x00ffffff
     44 
     45 extern	int	yyparse __P((void));
     46 extern	int	yydebug;
     47 extern	FILE	*yyin;
     48 
     49 static	iphtable_t	ipht;
     50 static	iphtent_t	iphte;
     51 static	ip_pool_t	iplo;
     52 static	ippool_dst_t	ipld;
     53 static	ioctlfunc_t	poolioctl = NULL;
     54 static	char		poolname[FR_GROUPLEN];
     55 
     56 static iphtent_t *add_htablehosts __P((char *));
     57 static ip_pool_node_t *add_poolhosts __P((char *));
     58 static ip_pool_node_t *read_whoisfile __P((char *));
     59 static void setadflen __P((addrfamily_t *));
     60 
     61 %}
     62 
     63 %union	{
     64 	char	*str;
     65 	u_32_t	num;
     66 	struct	in_addr	ip4;
     67 	struct	alist_s	*alist;
     68 	addrfamily_t	adrmsk[2];
     69 	iphtent_t	*ipe;
     70 	ip_pool_node_t	*ipp;
     71 	ipf_dstnode_t	*ipd;
     72 	addrfamily_t	ipa;
     73 	i6addr_t	ip6;
     74 }
     75 
     76 %token  <num>	YY_NUMBER YY_HEX
     77 %token  <str>	YY_STR
     78 %token  <ip6>	YY_IPV6
     79 %token	YY_COMMENT
     80 %token	YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
     81 %token	YY_RANGE_OUT YY_RANGE_IN
     82 %token	IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT IPT_ALL
     83 %token	IPT_TABLE IPT_GROUPMAP IPT_HASH IPT_SRCHASH IPT_DSTHASH
     84 %token	IPT_ROLE IPT_TYPE IPT_TREE
     85 %token	IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME IPT_POLICY
     86 %token	IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN
     87 %token	IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION
     88 %token	IPT_WHOIS IPT_FILE
     89 %type	<num> role table inout unit dstopts weighting
     90 %type	<ipp> ipftree range addrlist
     91 %type	<adrmsk> addrmask
     92 %type	<ipe> ipfgroup ipfhash hashlist hashentry
     93 %type	<ipe> groupentry setgrouplist grouplist
     94 %type	<ipa> ipaddr mask
     95 %type	<ip4> ipv4
     96 %type	<str> number setgroup name
     97 %type	<ipd> dstentry dstentries dstlist
     98 
     99 %%
    100 file:	line
    101 	| assign
    102 	| file line
    103 	| file assign
    104 	;
    105 
    106 line:	table role ipftree eol		{ ip_pool_node_t *n;
    107 					  iplo.ipo_unit = $2;
    108 					  iplo.ipo_list = $3;
    109 					  load_pool(&iplo, poolioctl);
    110 					  while ((n = $3) != NULL) {
    111 						$3 = n->ipn_next;
    112 						free(n);
    113 					  }
    114 					  resetlexer();
    115 					  use_inet6 = 0;
    116 					}
    117 	| table role ipfhash eol	{ iphtent_t *h;
    118 					  ipht.iph_unit = $2;
    119 					  ipht.iph_type = IPHASH_LOOKUP;
    120 					  load_hash(&ipht, $3, poolioctl);
    121 					  while ((h = $3) != NULL) {
    122 						$3 = h->ipe_next;
    123 						free(h);
    124 					  }
    125 					  resetlexer();
    126 					  use_inet6 = 0;
    127 					}
    128 	| groupmap role number ipfgroup eol
    129 					{ iphtent_t *h;
    130 					  ipht.iph_unit = $2;
    131 					  strncpy(ipht.iph_name, $3,
    132 						  sizeof(ipht.iph_name));
    133 					  ipht.iph_type = IPHASH_GROUPMAP;
    134 					  load_hash(&ipht, $4, poolioctl);
    135 					  while ((h = $4) != NULL) {
    136 						$4 = h->ipe_next;
    137 						free(h);
    138 					  }
    139 					  resetlexer();
    140 					  use_inet6 = 0;
    141 					}
    142 	| YY_COMMENT
    143 	| poolline eol
    144 	;
    145 
    146 eol:	';'
    147 	;
    148 
    149 assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
    150 					  resetlexer();
    151 					  free($1);
    152 					  free($3);
    153 					  yyvarnext = 0;
    154 					}
    155 	;
    156 
    157 assigning:
    158 	'='				{ yyvarnext = 1; }
    159 	;
    160 
    161 table:	IPT_TABLE		{ bzero((char *)&ipht, sizeof(ipht));
    162 				  bzero((char *)&iphte, sizeof(iphte));
    163 				  bzero((char *)&iplo, sizeof(iplo));
    164 				  bzero((char *)&ipld, sizeof(ipld));
    165 				  *ipht.iph_name = '\0';
    166 				  iplo.ipo_flags = IPHASH_ANON;
    167 				  iplo.ipo_name[0] = '\0';
    168 				}
    169 	;
    170 
    171 groupmap:
    172 	IPT_GROUPMAP inout	{ bzero((char *)&ipht, sizeof(ipht));
    173 				  bzero((char *)&iphte, sizeof(iphte));
    174 				  *ipht.iph_name = '\0';
    175 				  ipht.iph_unit = IPHASH_GROUPMAP;
    176 				  ipht.iph_flags = $2;
    177 				}
    178 	;
    179 
    180 inout:	IPT_IN				{ $$ = FR_INQUE; }
    181 	| IPT_OUT			{ $$ = FR_OUTQUE; }
    182 	;
    183 
    184 role:	IPT_ROLE '=' unit		{ $$ = $3; }
    185 	;
    186 
    187 unit:	IPT_IPF				{ $$ = IPL_LOGIPF; }
    188 	| IPT_NAT			{ $$ = IPL_LOGNAT; }
    189 	| IPT_AUTH			{ $$ = IPL_LOGAUTH; }
    190 	| IPT_COUNT			{ $$ = IPL_LOGCOUNT; }
    191 	| IPT_ALL			{ $$ = IPL_LOGALL; }
    192 	;
    193 
    194 ipftree:
    195 	IPT_TYPE '=' IPT_TREE number start addrlist end
    196 					{ strncpy(iplo.ipo_name, $4,
    197 						  sizeof(iplo.ipo_name));
    198 					  $$ = $6;
    199 					}
    200 	;
    201 
    202 ipfhash:
    203 	IPT_TYPE '=' IPT_HASH number hashopts start hashlist end
    204 					{ strncpy(ipht.iph_name, $4,
    205 						  sizeof(ipht.iph_name));
    206 					  $$ = $7;
    207 					}
    208 	;
    209 
    210 ipfgroup:
    211 	setgroup hashopts start grouplist end
    212 					{ iphtent_t *e;
    213 					  for (e = $4; e != NULL;
    214 					       e = e->ipe_next)
    215 						if (e->ipe_group[0] == '\0')
    216 							strncpy(e->ipe_group,
    217 								$1,
    218 								FR_GROUPLEN);
    219 					  $$ = $4;
    220 					  free($1);
    221 					}
    222 	| hashopts start setgrouplist end
    223 					{ $$ = $3; }
    224 	;
    225 
    226 number:	IPT_NUM '=' YY_NUMBER			{ sprintf(poolname, "%u", $3);
    227 						  $$ = poolname;
    228 						}
    229 	| IPT_NAME '=' YY_STR			{ strncpy(poolname, $3,
    230 							  FR_GROUPLEN);
    231 						  poolname[FR_GROUPLEN-1]='\0';
    232 						  free($3);
    233 						  $$ = poolname;
    234 						}
    235 	|					{ $$ = ""; }
    236 	;
    237 
    238 setgroup:
    239 	IPT_GROUP '=' YY_STR		{ char tmp[FR_GROUPLEN+1];
    240 					  strncpy(tmp, $3, FR_GROUPLEN);
    241 					  $$ = strdup(tmp);
    242 					  free($3);
    243 					}
    244 	| IPT_GROUP '=' YY_NUMBER	{ char tmp[FR_GROUPLEN+1];
    245 					  sprintf(tmp, "%u", $3);
    246 					  $$ = strdup(tmp);
    247 					}
    248 	;
    249 
    250 hashopts:
    251 	| size
    252 	| seed
    253 	| size seed
    254 	;
    255 
    256 addrlist:
    257 	';'				{ $$ = NULL; }
    258 	| range next addrlist		{ $$ = $1;
    259 					  while ($1->ipn_next != NULL)
    260 						$1 = $1->ipn_next;
    261 					  $1->ipn_next = $3;
    262 					}
    263 	| range next			{ $$ = $1; }
    264 	;
    265 
    266 grouplist:
    267 	';'				{ $$ = NULL; }
    268 	| groupentry next grouplist	{ $$ = $1; $1->ipe_next = $3; }
    269 	| addrmask next grouplist	{ $$ = calloc(1, sizeof(iphtent_t));
    270 					  $$->ipe_addr = $1[0].adf_addr;
    271 					  $$->ipe_mask = $1[1].adf_addr;
    272 					  $$->ipe_family = $1[0].adf_family;
    273 					  $$->ipe_next = $3;
    274 					}
    275 	| groupentry next		{ $$ = $1; }
    276 	| addrmask next			{ $$ = calloc(1, sizeof(iphtent_t));
    277 					  $$->ipe_addr = $1[0].adf_addr;
    278 					  $$->ipe_mask = $1[1].adf_addr;
    279 #ifdef AF_INET6
    280 					  if (use_inet6)
    281 						$$->ipe_family = AF_INET6;
    282 					  else
    283 #endif
    284 						$$->ipe_family = AF_INET;
    285 					}
    286 	| YY_STR			{ $$ = add_htablehosts($1);
    287 					  free($1);
    288 					}
    289 	;
    290 
    291 setgrouplist:
    292 	';'				{ $$ = NULL; }
    293 	| groupentry next		{ $$ = $1; }
    294 	| groupentry next setgrouplist	{ $1->ipe_next = $3; $$ = $1; }
    295 	;
    296 
    297 groupentry:
    298 	addrmask ',' setgroup		{ $$ = calloc(1, sizeof(iphtent_t));
    299 					  $$->ipe_addr = $1[0].adf_addr;
    300 					  $$->ipe_mask = $1[1].adf_addr;
    301 					  strncpy($$->ipe_group, $3,
    302 						  FR_GROUPLEN);
    303 #ifdef AF_INET6
    304 					  if (use_inet6)
    305 						$$->ipe_family = AF_INET6;
    306 					  else
    307 #endif
    308 						$$->ipe_family = AF_INET;
    309 					  free($3);
    310 					}
    311 	;
    312 
    313 range:	addrmask			{ $$ = calloc(1, sizeof(*$$));
    314 					  $$->ipn_info = 0;
    315 					  $$->ipn_addr = $1[0];
    316 					  $$->ipn_mask = $1[1];
    317 					}
    318 	| '!' addrmask			{ $$ = calloc(1, sizeof(*$$));
    319 					  $$->ipn_info = 1;
    320 					  $$->ipn_addr = $2[0];
    321 					  $$->ipn_mask = $2[1];
    322 					}
    323 	| YY_STR			{ $$ = add_poolhosts($1);
    324 					  free($1);
    325 					}
    326 	| IPT_WHOIS IPT_FILE YY_STR	{ $$ = read_whoisfile($3);
    327 					  free($3);
    328 					}
    329 	;
    330 
    331 hashlist:
    332 	';'				{ $$ = NULL; }
    333 	| hashentry next		{ $$ = $1; }
    334 	| hashentry next hashlist	{ $1->ipe_next = $3; $$ = $1; }
    335 	;
    336 
    337 hashentry:
    338 	addrmask 		{ $$ = calloc(1, sizeof(iphtent_t));
    339 				  $$->ipe_addr = $1[0].adf_addr;
    340 				  $$->ipe_mask = $1[1].adf_addr;
    341 #ifdef USE_INET6
    342 				  if (use_inet6)
    343 					$$->ipe_family = AF_INET6;
    344 				  else
    345 #endif
    346 					$$->ipe_family = AF_INET;
    347 				}
    348 	| YY_STR		{ $$ = add_htablehosts($1);
    349 				  free($1);
    350 				}
    351 	;
    352 
    353 addrmask:
    354 	ipaddr '/' mask		{ $$[0] = $1;
    355 				  setadflen(&$$[0]);
    356 				  $$[1] = $3;
    357 				  $$[1].adf_len = $$[0].adf_len;
    358 				}
    359 	| ipaddr		{ $$[0] = $1;
    360 				  setadflen(&$$[1]);
    361 				  $$[1].adf_len = $$[0].adf_len;
    362 #ifdef USE_INET6
    363 				  if (use_inet6)
    364 					memset(&$$[1].adf_addr, 0xff,
    365 					       sizeof($$[1].adf_addr.in6));
    366 				  else
    367 #endif
    368 					memset(&$$[1].adf_addr, 0xff,
    369 					       sizeof($$[1].adf_addr.in4));
    370 				}
    371 	;
    372 
    373 ipaddr:	ipv4			{ $$.adf_addr.in4 = $1;
    374 				  $$.adf_family = AF_INET;
    375 				  setadflen(&$$);
    376 				  use_inet6 = 0;
    377 				}
    378 	| YY_NUMBER		{ $$.adf_addr.in4.s_addr = htonl($1);
    379 				  $$.adf_family = AF_INET;
    380 				  setadflen(&$$);
    381 				  use_inet6 = 0;
    382 				}
    383 	| YY_IPV6		{ $$.adf_addr = $1;
    384 				  $$.adf_family = AF_INET6;
    385 				  setadflen(&$$);
    386 				  use_inet6 = 1;
    387 				}
    388 	;
    389 
    390 mask:	YY_NUMBER	{ bzero(&$$, sizeof($$));
    391 			  if (use_inet6) {
    392 				if (ntomask(AF_INET6, $1,
    393 					    (u_32_t *)&$$.adf_addr) == -1)
    394 					yyerror("bad bitmask");
    395 			  } else {
    396 				if (ntomask(AF_INET, $1,
    397 					    (u_32_t *)&$$.adf_addr.in4) == -1)
    398 					yyerror("bad bitmask");
    399 			  }
    400 			}
    401 	| ipv4		{ bzero(&$$, sizeof($$));
    402 			  $$.adf_addr.in4 = $1;
    403 			}
    404 	| YY_IPV6	{ bzero(&$$, sizeof($$));
    405 			  $$.adf_addr = $1;
    406 			}
    407 	;
    408 
    409 size:	IPT_SIZE '=' YY_NUMBER		{ ipht.iph_size = $3; }
    410 	;
    411 
    412 seed:	IPT_SEED '=' YY_NUMBER		{ ipht.iph_seed = $3; }
    413 	;
    414 
    415 ipv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
    416 		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
    417 			yyerror("Invalid octet string for IP address");
    418 			return 0;
    419 		  }
    420 		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
    421 		  $$.s_addr = htonl($$.s_addr);
    422 		}
    423 	;
    424 
    425 next:	';'				{ yyexpectaddr = 1; }
    426 	;
    427 
    428 start:	'{'				{ yyexpectaddr = 1; }
    429 	;
    430 
    431 end:	'}'				{ yyexpectaddr = 0; }
    432 	;
    433 
    434 poolline:
    435 	IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')'
    436 	start dstlist end
    437 					{ bzero((char *)&ipld, sizeof(ipld));
    438 					  strncpy(ipld.ipld_name, $6,
    439 						  sizeof(ipld.ipld_name));
    440 					  ipld.ipld_unit = $2;
    441 					  ipld.ipld_policy = $8;
    442 					  load_dstlist(&ipld, poolioctl, $11);
    443 					  resetlexer();
    444 					  use_inet6 = 0;
    445 					  free($6);
    446 					}
    447 	| IPT_POOL unit '/' IPT_TREE '(' name ';' ')'
    448 	  start addrlist end
    449 					{ bzero((char *)&iplo, sizeof(iplo));
    450 					  strncpy(iplo.ipo_name, $6,
    451 						  sizeof(iplo.ipo_name));
    452 					  iplo.ipo_list = $10;
    453 					  iplo.ipo_unit = $2;
    454 					  load_pool(&iplo, poolioctl);
    455 					  resetlexer();
    456 					  use_inet6 = 0;
    457 					  free($6);
    458 					}
    459 	| IPT_POOL '(' name ';' ')' start addrlist end
    460 					{ bzero((char *)&iplo, sizeof(iplo));
    461 					  strncpy(iplo.ipo_name, $3,
    462 						  sizeof(iplo.ipo_name));
    463 					  iplo.ipo_list = $7;
    464 					  iplo.ipo_unit = IPL_LOGALL;
    465 					  load_pool(&iplo, poolioctl);
    466 					  resetlexer();
    467 					  use_inet6 = 0;
    468 					  free($3);
    469 					}
    470 	| IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')'
    471 	  start hashlist end
    472 					{ iphtent_t *h;
    473 					  bzero((char *)&ipht, sizeof(ipht));
    474 					  strncpy(ipht.iph_name, $6,
    475 						  sizeof(ipht.iph_name));
    476 					  ipht.iph_unit = $2;
    477 					  load_hash(&ipht, $11, poolioctl);
    478 					  while ((h = ipht.iph_list) != NULL) {
    479 						ipht.iph_list = h->ipe_next;
    480 						free(h);
    481 					  }
    482 					  resetlexer();
    483 					  use_inet6 = 0;
    484 					  free($6);
    485 					}
    486 	| IPT_GROUPMAP '(' name ';' inout ';' ')'
    487 	  start setgrouplist end
    488 					{ iphtent_t *h;
    489 					  bzero((char *)&ipht, sizeof(ipht));
    490 					  strncpy(ipht.iph_name, $3,
    491 						  sizeof(ipht.iph_name));
    492 					  ipht.iph_type = IPHASH_GROUPMAP;
    493 					  ipht.iph_unit = IPL_LOGIPF;
    494 					  ipht.iph_flags = $5;
    495 					  load_hash(&ipht, $9, poolioctl);
    496 					  while ((h = ipht.iph_list) != NULL) {
    497 						ipht.iph_list = h->ipe_next;
    498 						free(h);
    499 					  }
    500 					  resetlexer();
    501 					  use_inet6 = 0;
    502 					  free($3);
    503 					}
    504 	;
    505 
    506 name:	IPT_NAME YY_STR			{ $$ = $2; }
    507 	| IPT_NUM YY_NUMBER		{ char name[80];
    508 					  sprintf(name, "%d", $2);
    509 					  $$ = strdup(name);
    510 					}
    511 	;
    512 
    513 hashoptlist:
    514 	| hashopt ';'
    515 	| hashoptlist ';' hashopt ';'
    516 	;
    517 hashopt:
    518 	IPT_SIZE YY_NUMBER
    519 	| IPT_SEED YY_NUMBER
    520 	;
    521 
    522 dstlist:
    523 	dstentries			{ $$ = $1; }
    524 	| ';'				{ $$ = NULL; }
    525 	;
    526 
    527 dstentries:
    528 	dstentry next			{ $$ = $1; }
    529 	| dstentry next dstentries	{ $1->ipfd_next = $3; $$ = $1; }
    530 	;
    531 
    532 dstentry:
    533 	YY_STR ':' ipaddr	{ int size = sizeof(*$$) + strlen($1) + 1;
    534 				  $$ = calloc(1, size);
    535 				  if ($$ != NULL) {
    536 					$$->ipfd_dest.fd_name = strlen($1) + 1;
    537 					bcopy($1, $$->ipfd_names,
    538 					      $$->ipfd_dest.fd_name);
    539 					$$->ipfd_dest.fd_addr = $3;
    540 					$$->ipfd_size = size;
    541 				  }
    542 				  free($1);
    543 				}
    544 	| ipaddr		{ $$ = calloc(1, sizeof(*$$));
    545 				  if ($$ != NULL) {
    546 					$$->ipfd_dest.fd_name = -1;
    547 					$$->ipfd_dest.fd_addr = $1;
    548 					$$->ipfd_size = sizeof(*$$);
    549 				  }
    550 				}
    551 	;
    552 
    553 dstopts:
    554 						{ $$ = IPLDP_NONE; }
    555 	| IPT_POLICY IPT_ROUNDROBIN ';'		{ $$ = IPLDP_ROUNDROBIN; }
    556 	| IPT_POLICY IPT_WEIGHTED weighting ';'	{ $$ = $3; }
    557 	| IPT_POLICY IPT_RANDOM ';'		{ $$ = IPLDP_RANDOM; }
    558 	| IPT_POLICY IPT_HASH ';'		{ $$ = IPLDP_HASHED; }
    559 	| IPT_POLICY IPT_SRCHASH ';'		{ $$ = IPLDP_SRCHASH; }
    560 	| IPT_POLICY IPT_DSTHASH ';'		{ $$ = IPLDP_DSTHASH; }
    561 	;
    562 
    563 weighting:
    564 	IPT_CONNECTION				{ $$ = IPLDP_CONNECTION; }
    565 	;
    566 %%
    567 static	wordtab_t	yywords[] = {
    568 	{ "all",		IPT_ALL },
    569 	{ "auth",		IPT_AUTH },
    570 	{ "connection",		IPT_CONNECTION },
    571 	{ "count",		IPT_COUNT },
    572 	{ "dst-hash",		IPT_DSTHASH },
    573 	{ "dstlist",		IPT_DSTLIST },
    574 	{ "file",		IPT_FILE },
    575 	{ "group",		IPT_GROUP },
    576 	{ "group-map",		IPT_GROUPMAP },
    577 	{ "hash",		IPT_HASH },
    578 	{ "in",			IPT_IN },
    579 	{ "ipf",		IPT_IPF },
    580 	{ "name",		IPT_NAME },
    581 	{ "nat",		IPT_NAT },
    582 	{ "number",		IPT_NUM },
    583 	{ "out",		IPT_OUT },
    584 	{ "policy",		IPT_POLICY },
    585 	{ "pool",		IPT_POOL },
    586 	{ "random",		IPT_RANDOM },
    587 	{ "round-robin",	IPT_ROUNDROBIN },
    588 	{ "role",		IPT_ROLE },
    589 	{ "seed",		IPT_SEED },
    590 	{ "size",		IPT_SIZE },
    591 	{ "src-hash",		IPT_SRCHASH },
    592 	{ "table",		IPT_TABLE },
    593 	{ "tree",		IPT_TREE },
    594 	{ "type",		IPT_TYPE },
    595 	{ "weighted",		IPT_WEIGHTED },
    596 	{ "whois",		IPT_WHOIS },
    597 	{ NULL,			0 }
    598 };
    599 
    600 
    601 int ippool_parsefile(fd, filename, iocfunc)
    602 int fd;
    603 char *filename;
    604 ioctlfunc_t iocfunc;
    605 {
    606 	FILE *fp = NULL;
    607 	char *s;
    608 
    609 	yylineNum = 1;
    610 	(void) yysettab(yywords);
    611 
    612 	s = getenv("YYDEBUG");
    613 	if (s)
    614 		yydebug = atoi(s);
    615 	else
    616 		yydebug = 0;
    617 
    618 	if (strcmp(filename, "-")) {
    619 		fp = fopen(filename, "r");
    620 		if (!fp) {
    621 			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
    622 				STRERROR(errno));
    623 			return -1;
    624 		}
    625 	} else
    626 		fp = stdin;
    627 
    628 	while (ippool_parsesome(fd, fp, iocfunc) == 1)
    629 		;
    630 	if (fp != NULL)
    631 		fclose(fp);
    632 	return 0;
    633 }
    634 
    635 
    636 int ippool_parsesome(fd, fp, iocfunc)
    637 int fd;
    638 FILE *fp;
    639 ioctlfunc_t iocfunc;
    640 {
    641 	char *s;
    642 	int i;
    643 
    644 	poolioctl = iocfunc;
    645 
    646 	if (feof(fp))
    647 		return 0;
    648 	i = fgetc(fp);
    649 	if (i == EOF)
    650 		return 0;
    651 	if (ungetc(i, fp) == EOF)
    652 		return 0;
    653 	if (feof(fp))
    654 		return 0;
    655 	s = getenv("YYDEBUG");
    656 	if (s)
    657 		yydebug = atoi(s);
    658 	else
    659 		yydebug = 0;
    660 
    661 	yyin = fp;
    662 	yyparse();
    663 	return 1;
    664 }
    665 
    666 
    667 static iphtent_t *
    668 add_htablehosts(url)
    669 char *url;
    670 {
    671 	iphtent_t *htop, *hbot, *h;
    672 	alist_t *a, *hlist;
    673 
    674 	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
    675 		hlist = load_url(url);
    676 	} else {
    677 		use_inet6 = 0;
    678 
    679 		hlist = calloc(1, sizeof(*hlist));
    680 		if (hlist == NULL)
    681 			return NULL;
    682 
    683 		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
    684 			yyerror("Unknown hostname");
    685 		}
    686 	}
    687 
    688 	hbot = NULL;
    689 	htop = NULL;
    690 
    691 	for (a = hlist; a != NULL; a = a->al_next) {
    692 		h = calloc(1, sizeof(*h));
    693 		if (h == NULL)
    694 			break;
    695 
    696 		h->ipe_family = a->al_family;
    697 		h->ipe_addr = a->al_i6addr;
    698 		h->ipe_mask = a->al_i6mask;
    699 
    700 		if (hbot != NULL)
    701 			hbot->ipe_next = h;
    702 		else
    703 			htop = h;
    704 		hbot = h;
    705 	}
    706 
    707 	alist_free(hlist);
    708 
    709 	return htop;
    710 }
    711 
    712 
    713 static ip_pool_node_t *
    714 add_poolhosts(url)
    715 char *url;
    716 {
    717 	ip_pool_node_t *ptop, *pbot, *p;
    718 	alist_t *a, *hlist;
    719 
    720 	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
    721 		hlist = load_url(url);
    722 	} else {
    723 		use_inet6 = 0;
    724 
    725 		hlist = calloc(1, sizeof(*hlist));
    726 		if (hlist == NULL)
    727 			return NULL;
    728 
    729 		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
    730 			yyerror("Unknown hostname");
    731 		}
    732 	}
    733 
    734 	pbot = NULL;
    735 	ptop = NULL;
    736 
    737 	for (a = hlist; a != NULL; a = a->al_next) {
    738 		p = calloc(1, sizeof(*p));
    739 		if (p == NULL)
    740 			break;
    741 		p->ipn_mask.adf_addr = a->al_i6mask;
    742 
    743 		if (a->al_family == AF_INET) {
    744 			p->ipn_addr.adf_family = AF_INET;
    745 #ifdef USE_INET6
    746 		} else if (a->al_family == AF_INET6) {
    747 			p->ipn_addr.adf_family = AF_INET6;
    748 #endif
    749 		}
    750 		setadflen(&p->ipn_addr);
    751 		p->ipn_addr.adf_addr = a->al_i6addr;
    752 		p->ipn_info = a->al_not;
    753 		p->ipn_mask.adf_len = p->ipn_addr.adf_len;
    754 
    755 		if (pbot != NULL)
    756 			pbot->ipn_next = p;
    757 		else
    758 			ptop = p;
    759 		pbot = p;
    760 	}
    761 
    762 	alist_free(hlist);
    763 
    764 	return ptop;
    765 }
    766 
    767 
    768 ip_pool_node_t *
    769 read_whoisfile(file)
    770 	char *file;
    771 {
    772 	ip_pool_node_t *ntop, *ipn, node, *last;
    773 	char line[1024];
    774 	FILE *fp;
    775 
    776 	fp = fopen(file, "r");
    777 	if (fp == NULL)
    778 		return NULL;
    779 
    780 	last = NULL;
    781 	ntop = NULL;
    782 	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
    783 		line[sizeof(line) - 1] = '\0';
    784 
    785 		if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask))
    786 			continue;
    787 		ipn = calloc(1, sizeof(*ipn));
    788 		if (ipn == NULL)
    789 			continue;
    790 		ipn->ipn_addr = node.ipn_addr;
    791 		ipn->ipn_mask = node.ipn_mask;
    792 		if (last == NULL)
    793 			ntop = ipn;
    794 		else
    795 			last->ipn_next = ipn;
    796 		last = ipn;
    797 	}
    798 	fclose(fp);
    799 	return ntop;
    800 }
    801 
    802 
    803 static void
    804 setadflen(afp)
    805 	addrfamily_t *afp;
    806 {
    807 	afp->adf_len = offsetof(addrfamily_t, adf_addr);
    808 	switch (afp->adf_family)
    809 	{
    810 	case AF_INET :
    811 		afp->adf_len += sizeof(struct in_addr);
    812 		break;
    813 #ifdef USE_INET6
    814 	case AF_INET6 :
    815 		afp->adf_len += sizeof(struct in6_addr);
    816 		break;
    817 #endif
    818 	default :
    819 		break;
    820 	}
    821 }
    822