1/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool_y.y 369245 2021-02-09 13:47:46Z git2svn $	*/
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
40extern	int	yyparse(void);
41extern	int	yydebug;
42extern	FILE	*yyin;
43
44static	iphtable_t	ipht;
45static	iphtent_t	iphte;
46static	ip_pool_t	iplo;
47static	ippool_dst_t	ipld;
48static	ioctlfunc_t	poolioctl = NULL;
49static	char		poolname[FR_GROUPLEN];
50
51static iphtent_t *add_htablehosts(char *);
52static ip_pool_node_t *add_poolhosts(char *);
53static ip_pool_node_t *read_whoisfile(char *);
54static 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%%
95file:	line
96	| assign
97	| file line
98	| file assign
99	;
100
101line:	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
141eol:	';'
142	;
143
144assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
145					  resetlexer();
146					  free($1);
147					  free($3);
148					  yyvarnext = 0;
149					}
150	;
151
152assigning:
153	'='				{ yyvarnext = 1; }
154	;
155
156table:	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
166groupmap:
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
175inout:	IPT_IN				{ $$ = FR_INQUE; }
176	| IPT_OUT			{ $$ = FR_OUTQUE; }
177	;
178
179role:	IPT_ROLE '=' unit		{ $$ = $3; }
180	;
181
182unit:	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
189ipftree:
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
197ipfhash:
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
205ipfgroup:
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
221number:	IPT_NUM '=' YY_NUMBER			{ sprintf(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
233setgroup:
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					  sprintf(tmp, "%u", $3);
241					  $$ = strdup(tmp);
242					}
243	;
244
245hashopts:
246	| size
247	| seed
248	| size seed
249	;
250
251addrlist:
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
261grouplist:
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 AF_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
286setgrouplist:
287	';'				{ $$ = NULL; }
288	| groupentry next		{ $$ = $1; }
289	| groupentry next setgrouplist	{ $1->ipe_next = $3; $$ = $1; }
290	;
291
292groupentry:
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 AF_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
308range:	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
342hashlist:
343	';'				{ $$ = NULL; }
344	| hashentry next		{ $$ = $1; }
345	| hashentry next hashlist	{ $1->ipe_next = $3; $$ = $1; }
346	;
347
348hashentry:
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
364addrmask:
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
384ipaddr:	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
401mask:	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
420size:	IPT_SIZE '=' YY_NUMBER		{ ipht.iph_size = $3; }
421	;
422
423seed:	IPT_SEED '=' YY_NUMBER		{ ipht.iph_seed = $3; }
424	;
425
426ipv4:	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
436next:	';'				{ yyexpectaddr = 1; }
437	;
438
439start:	'{'				{ yyexpectaddr = 1; }
440	;
441
442end:	'}'				{ yyexpectaddr = 0; }
443	;
444
445poolline:
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
517name:	IPT_NAME YY_STR			{ $$ = $2; }
518	| IPT_NUM YY_NUMBER		{ char name[80];
519					  sprintf(name, "%d", $2);
520					  $$ = strdup(name);
521					}
522	;
523
524hashoptlist:
525	| hashopt ';'
526	| hashoptlist ';' hashopt ';'
527	;
528hashopt:
529	IPT_SIZE YY_NUMBER
530	| IPT_SEED YY_NUMBER
531	;
532
533dstlist:
534	dstentries			{ $$ = $1; }
535	| ';'				{ $$ = NULL; }
536	;
537
538dstentries:
539	dstentry next			{ $$ = $1; }
540	| dstentry next dstentries	{ $1->ipfd_next = $3; $$ = $1; }
541	;
542
543dstentry:
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
564dstopts:
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
574weighting:
575	IPT_CONNECTION				{ $$ = IPLDP_CONNECTION; }
576	;
577%%
578static	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
612int ippool_parsefile(fd, filename, iocfunc)
613int fd;
614char *filename;
615ioctlfunc_t iocfunc;
616{
617	FILE *fp = NULL;
618	char *s;
619
620	yylineNum = 1;
621	(void) yysettab(yywords);
622
623	s = getenv("YYDEBUG");
624	if (s)
625		yydebug = atoi(s);
626	else
627		yydebug = 0;
628
629	if (strcmp(filename, "-")) {
630		fp = fopen(filename, "r");
631		if (!fp) {
632			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
633				STRERROR(errno));
634			return -1;
635		}
636	} else
637		fp = stdin;
638
639	while (ippool_parsesome(fd, fp, iocfunc) == 1)
640		;
641	if (fp != NULL)
642		fclose(fp);
643	return 0;
644}
645
646
647int ippool_parsesome(fd, fp, iocfunc)
648int fd;
649FILE *fp;
650ioctlfunc_t iocfunc;
651{
652	char *s;
653	int i;
654
655	poolioctl = iocfunc;
656
657	if (feof(fp))
658		return 0;
659	i = fgetc(fp);
660	if (i == EOF)
661		return 0;
662	if (ungetc(i, fp) == EOF)
663		return 0;
664	if (feof(fp))
665		return 0;
666	s = getenv("YYDEBUG");
667	if (s)
668		yydebug = atoi(s);
669	else
670		yydebug = 0;
671
672	yyin = fp;
673	yyparse();
674	return 1;
675}
676
677
678static iphtent_t *
679add_htablehosts(url)
680char *url;
681{
682	iphtent_t *htop, *hbot, *h;
683	alist_t *a, *hlist;
684
685	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
686		hlist = load_url(url);
687	} else {
688		use_inet6 = 0;
689
690		hlist = calloc(1, sizeof(*hlist));
691		if (hlist == NULL)
692			return NULL;
693
694		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
695			yyerror("Unknown hostname");
696		}
697	}
698
699	hbot = NULL;
700	htop = NULL;
701
702	for (a = hlist; a != NULL; a = a->al_next) {
703		h = calloc(1, sizeof(*h));
704		if (h == NULL)
705			break;
706
707		h->ipe_family = a->al_family;
708		h->ipe_addr = a->al_i6addr;
709		h->ipe_mask = a->al_i6mask;
710
711		if (hbot != NULL)
712			hbot->ipe_next = h;
713		else
714			htop = h;
715		hbot = h;
716	}
717
718	alist_free(hlist);
719
720	return htop;
721}
722
723
724static ip_pool_node_t *
725add_poolhosts(url)
726char *url;
727{
728	ip_pool_node_t *ptop, *pbot, *p;
729	alist_t *a, *hlist;
730
731	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
732		hlist = load_url(url);
733	} else {
734		use_inet6 = 0;
735
736		hlist = calloc(1, sizeof(*hlist));
737		if (hlist == NULL)
738			return NULL;
739
740		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
741			yyerror("Unknown hostname");
742		}
743	}
744
745	pbot = NULL;
746	ptop = NULL;
747
748	for (a = hlist; a != NULL; a = a->al_next) {
749		p = calloc(1, sizeof(*p));
750		if (p == NULL)
751			break;
752		p->ipn_mask.adf_addr = a->al_i6mask;
753
754		if (a->al_family == AF_INET) {
755			p->ipn_addr.adf_family = AF_INET;
756#ifdef USE_INET6
757		} else if (a->al_family == AF_INET6) {
758			p->ipn_addr.adf_family = AF_INET6;
759#endif
760		}
761		setadflen(&p->ipn_addr);
762		p->ipn_addr.adf_addr = a->al_i6addr;
763		p->ipn_info = a->al_not;
764		p->ipn_mask.adf_len = p->ipn_addr.adf_len;
765
766		if (pbot != NULL)
767			pbot->ipn_next = p;
768		else
769			ptop = p;
770		pbot = p;
771	}
772
773	alist_free(hlist);
774
775	return ptop;
776}
777
778
779ip_pool_node_t *
780read_whoisfile(file)
781	char *file;
782{
783	ip_pool_node_t *ntop, *ipn, node, *last;
784	char line[1024];
785	FILE *fp;
786
787	fp = fopen(file, "r");
788	if (fp == NULL)
789		return NULL;
790
791	last = NULL;
792	ntop = NULL;
793	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
794		line[sizeof(line) - 1] = '\0';
795
796		if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask))
797			continue;
798		ipn = calloc(1, sizeof(*ipn));
799		if (ipn == NULL)
800			continue;
801		ipn->ipn_addr = node.ipn_addr;
802		ipn->ipn_mask = node.ipn_mask;
803		if (last == NULL)
804			ntop = ipn;
805		else
806			last->ipn_next = ipn;
807		last = ipn;
808	}
809	fclose(fp);
810	return ntop;
811}
812
813
814static void
815setadflen(afp)
816	addrfamily_t *afp;
817{
818	afp->adf_len = offsetof(addrfamily_t, adf_addr);
819	switch (afp->adf_family)
820	{
821	case AF_INET :
822		afp->adf_len += sizeof(struct in_addr);
823		break;
824#ifdef USE_INET6
825	case AF_INET6 :
826		afp->adf_len += sizeof(struct in6_addr);
827		break;
828#endif
829	default :
830		break;
831	}
832}
833