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