]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ippool_y.y
MFV r349454:
[FreeBSD/FreeBSD.git] / contrib / ipfilter / tools / ippool_y.y
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 __P((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 __P((char *));
52 static ip_pool_node_t *add_poolhosts __P((char *));
53 static ip_pool_node_t *read_whoisfile __P((char *));
54 static void setadflen __P((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                   { 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
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                                           sprintf(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                                         }
313         | '!' addrmask                  { $$ = calloc(1, sizeof(*$$));
314                                           $$->ipn_info = 1;
315                                           $$->ipn_addr = $2[0];
316                                           $$->ipn_mask = $2[1];
317                                         }
318         | YY_STR                        { $$ = add_poolhosts($1);
319                                           free($1);
320                                         }
321         | IPT_WHOIS IPT_FILE YY_STR     { $$ = read_whoisfile($3);
322                                           free($3);
323                                         }
324         ;
325
326 hashlist:
327         ';'                             { $$ = NULL; }
328         | hashentry next                { $$ = $1; }
329         | hashentry next hashlist       { $1->ipe_next = $3; $$ = $1; }
330         ;
331
332 hashentry:
333         addrmask                { $$ = calloc(1, sizeof(iphtent_t));
334                                   $$->ipe_addr = $1[0].adf_addr;
335                                   $$->ipe_mask = $1[1].adf_addr;
336 #ifdef USE_INET6
337                                   if (use_inet6)
338                                         $$->ipe_family = AF_INET6;
339                                   else
340 #endif
341                                         $$->ipe_family = AF_INET;
342                                 }
343         | YY_STR                { $$ = add_htablehosts($1);
344                                   free($1);
345                                 }
346         ;
347
348 addrmask:
349         ipaddr '/' mask         { $$[0] = $1;
350                                   setadflen(&$$[0]);
351                                   $$[1] = $3;
352                                   $$[1].adf_len = $$[0].adf_len;
353                                 }
354         | ipaddr                { $$[0] = $1;
355                                   setadflen(&$$[1]);
356                                   $$[1].adf_len = $$[0].adf_len;
357 #ifdef USE_INET6
358                                   if (use_inet6)
359                                         memset(&$$[1].adf_addr, 0xff,
360                                                sizeof($$[1].adf_addr.in6));
361                                   else
362 #endif
363                                         memset(&$$[1].adf_addr, 0xff, 
364                                                sizeof($$[1].adf_addr.in4));
365                                 }
366         ;
367
368 ipaddr: ipv4                    { $$.adf_addr.in4 = $1;
369                                   $$.adf_family = AF_INET;
370                                   setadflen(&$$);
371                                   use_inet6 = 0;
372                                 }
373         | YY_NUMBER             { $$.adf_addr.in4.s_addr = htonl($1);
374                                   $$.adf_family = AF_INET;
375                                   setadflen(&$$);
376                                   use_inet6 = 0;
377                                 }
378         | YY_IPV6               { $$.adf_addr = $1;
379                                   $$.adf_family = AF_INET6;
380                                   setadflen(&$$);
381                                   use_inet6 = 1;
382                                 }
383         ;
384
385 mask:   YY_NUMBER       { bzero(&$$, sizeof($$));
386                           if (use_inet6) {
387                                 if (ntomask(AF_INET6, $1,
388                                             (u_32_t *)&$$.adf_addr) == -1)
389                                         yyerror("bad bitmask");
390                           } else {
391                                 if (ntomask(AF_INET, $1,
392                                             (u_32_t *)&$$.adf_addr.in4) == -1)
393                                         yyerror("bad bitmask");
394                           }
395                         }
396         | ipv4          { bzero(&$$, sizeof($$));
397                           $$.adf_addr.in4 = $1;
398                         }
399         | YY_IPV6       { bzero(&$$, sizeof($$));
400                           $$.adf_addr = $1;
401                         }
402         ;
403
404 size:   IPT_SIZE '=' YY_NUMBER          { ipht.iph_size = $3; }
405         ;
406
407 seed:   IPT_SEED '=' YY_NUMBER          { ipht.iph_seed = $3; }
408         ;
409
410 ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
411                 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
412                         yyerror("Invalid octet string for IP address");
413                         return 0;
414                   }
415                   $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
416                   $$.s_addr = htonl($$.s_addr);
417                 }
418         ;
419
420 next:   ';'                             { yyexpectaddr = 1; }
421         ;
422
423 start:  '{'                             { yyexpectaddr = 1; }
424         ;
425
426 end:    '}'                             { yyexpectaddr = 0; }
427         ;
428
429 poolline:
430         IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')'
431         start dstlist end
432                                         { bzero((char *)&ipld, sizeof(ipld));
433                                           strncpy(ipld.ipld_name, $6,
434                                                   sizeof(ipld.ipld_name));
435                                           ipld.ipld_unit = $2;
436                                           ipld.ipld_policy = $8;
437                                           load_dstlist(&ipld, poolioctl, $11);
438                                           resetlexer();
439                                           use_inet6 = 0;
440                                           free($6);
441                                         }
442         | IPT_POOL unit '/' IPT_TREE '(' name ';' ')'
443           start addrlist end
444                                         { bzero((char *)&iplo, sizeof(iplo));
445                                           strncpy(iplo.ipo_name, $6,
446                                                   sizeof(iplo.ipo_name));
447                                           iplo.ipo_list = $10;
448                                           iplo.ipo_unit = $2;
449                                           load_pool(&iplo, poolioctl);
450                                           resetlexer();
451                                           use_inet6 = 0;
452                                           free($6);
453                                         }
454         | IPT_POOL '(' name ';' ')' start addrlist end
455                                         { bzero((char *)&iplo, sizeof(iplo));
456                                           strncpy(iplo.ipo_name, $3,
457                                                   sizeof(iplo.ipo_name));
458                                           iplo.ipo_list = $7;
459                                           iplo.ipo_unit = IPL_LOGALL;
460                                           load_pool(&iplo, poolioctl);
461                                           resetlexer();
462                                           use_inet6 = 0;
463                                           free($3);
464                                         }
465         | IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')'
466           start hashlist end
467                                         { iphtent_t *h;
468                                           bzero((char *)&ipht, sizeof(ipht));
469                                           strncpy(ipht.iph_name, $6,
470                                                   sizeof(ipht.iph_name));
471                                           ipht.iph_unit = $2;
472                                           load_hash(&ipht, $11, poolioctl);
473                                           while ((h = ipht.iph_list) != NULL) {
474                                                 ipht.iph_list = h->ipe_next;
475                                                 free(h);
476                                           }
477                                           resetlexer();
478                                           use_inet6 = 0;
479                                           free($6);
480                                         }
481         | IPT_GROUPMAP '(' name ';' inout ';' ')'
482           start setgrouplist end
483                                         { iphtent_t *h;
484                                           bzero((char *)&ipht, sizeof(ipht));
485                                           strncpy(ipht.iph_name, $3,
486                                                   sizeof(ipht.iph_name));
487                                           ipht.iph_type = IPHASH_GROUPMAP;
488                                           ipht.iph_unit = IPL_LOGIPF;
489                                           ipht.iph_flags = $5;
490                                           load_hash(&ipht, $9, poolioctl);
491                                           while ((h = ipht.iph_list) != NULL) {
492                                                 ipht.iph_list = h->ipe_next;
493                                                 free(h);
494                                           }
495                                           resetlexer();
496                                           use_inet6 = 0;
497                                           free($3);
498                                         }
499         ;
500
501 name:   IPT_NAME YY_STR                 { $$ = $2; }
502         | IPT_NUM YY_NUMBER             { char name[80];
503                                           sprintf(name, "%d", $2);
504                                           $$ = strdup(name);
505                                         }
506         ;
507
508 hashoptlist:
509         | hashopt ';'
510         | hashoptlist ';' hashopt ';'
511         ;
512 hashopt:
513         IPT_SIZE YY_NUMBER
514         | IPT_SEED YY_NUMBER
515         ;
516
517 dstlist:
518         dstentries                      { $$ = $1; }
519         | ';'                           { $$ = NULL; }
520         ;
521
522 dstentries:
523         dstentry next                   { $$ = $1; }
524         | dstentry next dstentries      { $1->ipfd_next = $3; $$ = $1; }
525         ;
526
527 dstentry:
528         YY_STR ':' ipaddr       { int size = sizeof(*$$) + strlen($1) + 1;
529                                   $$ = calloc(1, size);
530                                   if ($$ != NULL) {
531                                         $$->ipfd_dest.fd_name = strlen($1) + 1;
532                                         bcopy($1, $$->ipfd_names,
533                                               $$->ipfd_dest.fd_name);
534                                         $$->ipfd_dest.fd_addr = $3;
535                                         $$->ipfd_size = size;
536                                   }
537                                   free($1);
538                                 }
539         | ipaddr                { $$ = calloc(1, sizeof(*$$));
540                                   if ($$ != NULL) {
541                                         $$->ipfd_dest.fd_name = -1;
542                                         $$->ipfd_dest.fd_addr = $1;
543                                         $$->ipfd_size = sizeof(*$$);
544                                   }
545                                 }
546         ;
547
548 dstopts:
549                                                 { $$ = IPLDP_NONE; }
550         | IPT_POLICY IPT_ROUNDROBIN ';'         { $$ = IPLDP_ROUNDROBIN; }
551         | IPT_POLICY IPT_WEIGHTED weighting ';' { $$ = $3; }
552         | IPT_POLICY IPT_RANDOM ';'             { $$ = IPLDP_RANDOM; }
553         | IPT_POLICY IPT_HASH ';'               { $$ = IPLDP_HASHED; }
554         | IPT_POLICY IPT_SRCHASH ';'            { $$ = IPLDP_SRCHASH; }
555         | IPT_POLICY IPT_DSTHASH ';'            { $$ = IPLDP_DSTHASH; }
556         ;
557
558 weighting:
559         IPT_CONNECTION                          { $$ = IPLDP_CONNECTION; }
560         ;
561 %%
562 static  wordtab_t       yywords[] = {
563         { "all",                IPT_ALL },
564         { "auth",               IPT_AUTH },
565         { "connection",         IPT_CONNECTION },
566         { "count",              IPT_COUNT },
567         { "dst-hash",           IPT_DSTHASH },
568         { "dstlist",            IPT_DSTLIST },
569         { "file",               IPT_FILE },
570         { "group",              IPT_GROUP },
571         { "group-map",          IPT_GROUPMAP },
572         { "hash",               IPT_HASH },
573         { "in",                 IPT_IN },
574         { "ipf",                IPT_IPF },
575         { "name",               IPT_NAME },
576         { "nat",                IPT_NAT },
577         { "number",             IPT_NUM },
578         { "out",                IPT_OUT },
579         { "policy",             IPT_POLICY },
580         { "pool",               IPT_POOL },
581         { "random",             IPT_RANDOM },
582         { "round-robin",        IPT_ROUNDROBIN },
583         { "role",               IPT_ROLE },
584         { "seed",               IPT_SEED },
585         { "size",               IPT_SIZE },
586         { "src-hash",           IPT_SRCHASH },
587         { "table",              IPT_TABLE },
588         { "tree",               IPT_TREE },
589         { "type",               IPT_TYPE },
590         { "weighted",           IPT_WEIGHTED },
591         { "whois",              IPT_WHOIS },
592         { NULL,                 0 }
593 };
594
595
596 int ippool_parsefile(fd, filename, iocfunc)
597 int fd;
598 char *filename;
599 ioctlfunc_t iocfunc;
600 {
601         FILE *fp = NULL;
602         char *s;
603
604         yylineNum = 1;
605         (void) yysettab(yywords);
606
607         s = getenv("YYDEBUG");
608         if (s)
609                 yydebug = atoi(s);
610         else
611                 yydebug = 0;
612
613         if (strcmp(filename, "-")) {
614                 fp = fopen(filename, "r");
615                 if (!fp) {
616                         fprintf(stderr, "fopen(%s) failed: %s\n", filename,
617                                 STRERROR(errno));
618                         return -1;
619                 }
620         } else
621                 fp = stdin;
622
623         while (ippool_parsesome(fd, fp, iocfunc) == 1)
624                 ;
625         if (fp != NULL)
626                 fclose(fp);
627         return 0;
628 }
629
630
631 int ippool_parsesome(fd, fp, iocfunc)
632 int fd;
633 FILE *fp;
634 ioctlfunc_t iocfunc;
635 {
636         char *s;
637         int i;
638
639         poolioctl = iocfunc;
640
641         if (feof(fp))
642                 return 0;
643         i = fgetc(fp);
644         if (i == EOF)
645                 return 0;
646         if (ungetc(i, fp) == EOF)
647                 return 0;
648         if (feof(fp))
649                 return 0;
650         s = getenv("YYDEBUG");
651         if (s)
652                 yydebug = atoi(s);
653         else
654                 yydebug = 0;
655
656         yyin = fp;
657         yyparse();
658         return 1;
659 }
660
661
662 static iphtent_t *
663 add_htablehosts(url)
664 char *url;
665 {
666         iphtent_t *htop, *hbot, *h;
667         alist_t *a, *hlist;
668
669         if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
670                 hlist = load_url(url);
671         } else {
672                 use_inet6 = 0;
673
674                 hlist = calloc(1, sizeof(*hlist));
675                 if (hlist == NULL)
676                         return NULL;
677
678                 if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
679                         yyerror("Unknown hostname");
680                 }
681         }
682
683         hbot = NULL;
684         htop = NULL;
685
686         for (a = hlist; a != NULL; a = a->al_next) {
687                 h = calloc(1, sizeof(*h));
688                 if (h == NULL)
689                         break;
690
691                 h->ipe_family = a->al_family;
692                 h->ipe_addr = a->al_i6addr;
693                 h->ipe_mask = a->al_i6mask;
694
695                 if (hbot != NULL)
696                         hbot->ipe_next = h;
697                 else
698                         htop = h;
699                 hbot = h;
700         }
701
702         alist_free(hlist);
703
704         return htop;
705 }
706
707
708 static ip_pool_node_t *
709 add_poolhosts(url)
710 char *url;
711 {
712         ip_pool_node_t *ptop, *pbot, *p;
713         alist_t *a, *hlist;
714
715         if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
716                 hlist = load_url(url);
717         } else {
718                 use_inet6 = 0;
719
720                 hlist = calloc(1, sizeof(*hlist));
721                 if (hlist == NULL)
722                         return NULL;
723
724                 if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
725                         yyerror("Unknown hostname");
726                 }
727         }
728
729         pbot = NULL;
730         ptop = NULL;
731
732         for (a = hlist; a != NULL; a = a->al_next) {
733                 p = calloc(1, sizeof(*p));
734                 if (p == NULL)
735                         break;
736                 p->ipn_mask.adf_addr = a->al_i6mask;
737
738                 if (a->al_family == AF_INET) {
739                         p->ipn_addr.adf_family = AF_INET;
740 #ifdef USE_INET6
741                 } else if (a->al_family == AF_INET6) {
742                         p->ipn_addr.adf_family = AF_INET6;
743 #endif
744                 }
745                 setadflen(&p->ipn_addr);
746                 p->ipn_addr.adf_addr = a->al_i6addr;
747                 p->ipn_info = a->al_not;
748                 p->ipn_mask.adf_len = p->ipn_addr.adf_len;
749
750                 if (pbot != NULL)
751                         pbot->ipn_next = p;
752                 else
753                         ptop = p;
754                 pbot = p;
755         }
756
757         alist_free(hlist);
758
759         return ptop;
760 }
761
762
763 ip_pool_node_t *
764 read_whoisfile(file)
765         char *file;
766 {
767         ip_pool_node_t *ntop, *ipn, node, *last;
768         char line[1024];
769         FILE *fp;
770
771         fp = fopen(file, "r");
772         if (fp == NULL)
773                 return NULL;
774
775         last = NULL;
776         ntop = NULL;
777         while (fgets(line, sizeof(line) - 1, fp) != NULL) {
778                 line[sizeof(line) - 1] = '\0';
779
780                 if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask))
781                         continue;
782                 ipn = calloc(1, sizeof(*ipn));
783                 if (ipn == NULL)
784                         continue;
785                 ipn->ipn_addr = node.ipn_addr;
786                 ipn->ipn_mask = node.ipn_mask;
787                 if (last == NULL)
788                         ntop = ipn;
789                 else
790                         last->ipn_next = ipn;
791                 last = ipn;
792         }
793         fclose(fp);
794         return ntop;
795 }
796
797
798 static void
799 setadflen(afp)
800         addrfamily_t *afp;
801 {
802         afp->adf_len = offsetof(addrfamily_t, adf_addr);
803         switch (afp->adf_family)
804         {
805         case AF_INET :
806                 afp->adf_len += sizeof(struct in_addr);
807                 break;
808 #ifdef USE_INET6
809         case AF_INET6 :
810                 afp->adf_len += sizeof(struct in6_addr);
811                 break;
812 #endif
813         default :
814                 break;
815         }
816 }