ippool_y.y revision 255332
1/*	$FreeBSD: head/contrib/ipfilter/tools/ippool_y.y 255332 2013-09-06 23:11:19Z cy $	*/
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
45extern	int	yyparse __P((void));
46extern	int	yydebug;
47extern	FILE	*yyin;
48
49static	iphtable_t	ipht;
50static	iphtent_t	iphte;
51static	ip_pool_t	iplo;
52static	ippool_dst_t	ipld;
53static	ioctlfunc_t	poolioctl = NULL;
54static	char		poolname[FR_GROUPLEN];
55
56static iphtent_t *add_htablehosts __P((char *));
57static ip_pool_node_t *add_poolhosts __P((char *));
58static ip_pool_node_t *read_whoisfile __P((char *));
59static 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%%
100file:	line
101	| assign
102	| file line
103	| file assign
104	;
105
106line:	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
146eol:	';'
147	;
148
149assign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
150					  resetlexer();
151					  free($1);
152					  free($3);
153					  yyvarnext = 0;
154					}
155	;
156
157assigning:
158	'='				{ yyvarnext = 1; }
159	;
160
161table:	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
171groupmap:
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
180inout:	IPT_IN				{ $$ = FR_INQUE; }
181	| IPT_OUT			{ $$ = FR_OUTQUE; }
182	;
183
184role:	IPT_ROLE '=' unit		{ $$ = $3; }
185	;
186
187unit:	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
194ipftree:
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
202ipfhash:
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
210ipfgroup:
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
226number:	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
238setgroup:
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
250hashopts:
251	| size
252	| seed
253	| size seed
254	;
255
256addrlist:
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
266grouplist:
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
291setgrouplist:
292	';'				{ $$ = NULL; }
293	| groupentry next		{ $$ = $1; }
294	| groupentry next setgrouplist	{ $1->ipe_next = $3; $$ = $1; }
295	;
296
297groupentry:
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
313range:	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
331hashlist:
332	';'				{ $$ = NULL; }
333	| hashentry next		{ $$ = $1; }
334	| hashentry next hashlist	{ $1->ipe_next = $3; $$ = $1; }
335	;
336
337hashentry:
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
353addrmask:
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
373ipaddr:	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
390mask:	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
409size:	IPT_SIZE '=' YY_NUMBER		{ ipht.iph_size = $3; }
410	;
411
412seed:	IPT_SEED '=' YY_NUMBER		{ ipht.iph_seed = $3; }
413	;
414
415ipv4:	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
425next:	';'				{ yyexpectaddr = 1; }
426	;
427
428start:	'{'				{ yyexpectaddr = 1; }
429	;
430
431end:	'}'				{ yyexpectaddr = 0; }
432	;
433
434poolline:
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
506name:	IPT_NAME YY_STR			{ $$ = $2; }
507	| IPT_NUM YY_NUMBER		{ char name[80];
508					  sprintf(name, "%d", $2);
509					  $$ = strdup(name);
510					}
511	;
512
513hashoptlist:
514	| hashopt ';'
515	| hashoptlist ';' hashopt ';'
516	;
517hashopt:
518	IPT_SIZE YY_NUMBER
519	| IPT_SEED YY_NUMBER
520	;
521
522dstlist:
523	dstentries			{ $$ = $1; }
524	| ';'				{ $$ = NULL; }
525	;
526
527dstentries:
528	dstentry next			{ $$ = $1; }
529	| dstentry next dstentries	{ $1->ipfd_next = $3; $$ = $1; }
530	;
531
532dstentry:
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
553dstopts:
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
563weighting:
564	IPT_CONNECTION				{ $$ = IPLDP_CONNECTION; }
565	;
566%%
567static	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
601int ippool_parsefile(fd, filename, iocfunc)
602int fd;
603char *filename;
604ioctlfunc_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
636int ippool_parsesome(fd, fp, iocfunc)
637int fd;
638FILE *fp;
639ioctlfunc_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
667static iphtent_t *
668add_htablehosts(url)
669char *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
713static ip_pool_node_t *
714add_poolhosts(url)
715char *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
768ip_pool_node_t *
769read_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
803static void
804setadflen(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