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