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