]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ippool_y.y
Bring down 0.4.5 vendor files and other catchups with the distribution tarball.
[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 #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
42 extern  int     yyparse __P((void));
43 extern  int     yydebug;
44 extern  FILE    *yyin;
45
46 static  iphtable_t      ipht;
47 static  iphtent_t       iphte;
48 static  ip_pool_t       iplo;
49 static  ippool_dst_t    ipld;
50 static  ioctlfunc_t     poolioctl = NULL;
51 static  char            poolname[FR_GROUPLEN];
52
53 static iphtent_t *add_htablehosts __P((char *));
54 static ip_pool_node_t *add_poolhosts __P((char *));
55 static ip_pool_node_t *read_whoisfile __P((char *));
56 static 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 %%
97 file:   line
98         | assign
99         | file line
100         | file assign
101         ;
102
103 line:   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
143 eol:    ';'
144         ;
145
146 assign: YY_STR assigning YY_STR ';'     { set_variable($1, $3);
147                                           resetlexer();
148                                           free($1);
149                                           free($3);
150                                           yyvarnext = 0;
151                                         }
152         ;
153
154 assigning:
155         '='                             { yyvarnext = 1; }
156         ;
157
158 table:  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
168 groupmap:
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
177 inout:  IPT_IN                          { $$ = FR_INQUE; }
178         | IPT_OUT                       { $$ = FR_OUTQUE; }
179         ;
180
181 role:   IPT_ROLE '=' unit               { $$ = $3; }
182         ;
183
184 unit:   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
191 ipftree:
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
199 ipfhash:
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
207 ipfgroup:
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
223 number: 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
235 setgroup:
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
247 hashopts:
248         | size
249         | seed
250         | size seed
251         ;
252
253 addrlist:
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
263 grouplist:
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
288 setgrouplist:
289         ';'                             { $$ = NULL; }
290         | groupentry next               { $$ = $1; }
291         | groupentry next setgrouplist  { $1->ipe_next = $3; $$ = $1; }
292         ;
293
294 groupentry:
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
310 range:  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
328 hashlist:
329         ';'                             { $$ = NULL; }
330         | hashentry next                { $$ = $1; }
331         | hashentry next hashlist       { $1->ipe_next = $3; $$ = $1; }
332         ;
333
334 hashentry:
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
350 addrmask:
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
370 ipaddr: 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
387 mask:   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
406 size:   IPT_SIZE '=' YY_NUMBER          { ipht.iph_size = $3; }
407         ;
408
409 seed:   IPT_SEED '=' YY_NUMBER          { ipht.iph_seed = $3; }
410         ;
411
412 ipv4:   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
422 next:   ';'                             { yyexpectaddr = 1; }
423         ;
424
425 start:  '{'                             { yyexpectaddr = 1; }
426         ;
427
428 end:    '}'                             { yyexpectaddr = 0; }
429         ;
430
431 poolline:
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
503 name:   IPT_NAME YY_STR                 { $$ = $2; }
504         | IPT_NUM YY_NUMBER             { char name[80];
505                                           sprintf(name, "%d", $2);
506                                           $$ = strdup(name);
507                                         }
508         ;
509
510 hashoptlist:
511         | hashopt ';'
512         | hashoptlist ';' hashopt ';'
513         ;
514 hashopt:
515         IPT_SIZE YY_NUMBER
516         | IPT_SEED YY_NUMBER
517         ;
518
519 dstlist:
520         dstentries                      { $$ = $1; }
521         | ';'                           { $$ = NULL; }
522         ;
523
524 dstentries:
525         dstentry next                   { $$ = $1; }
526         | dstentry next dstentries      { $1->ipfd_next = $3; $$ = $1; }
527         ;
528
529 dstentry:
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
550 dstopts:
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
560 weighting:
561         IPT_CONNECTION                          { $$ = IPLDP_CONNECTION; }
562         ;
563 %%
564 static  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
598 int ippool_parsefile(fd, filename, iocfunc)
599 int fd;
600 char *filename;
601 ioctlfunc_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
633 int ippool_parsesome(fd, fp, iocfunc)
634 int fd;
635 FILE *fp;
636 ioctlfunc_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
664 static iphtent_t *
665 add_htablehosts(url)
666 char *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
710 static ip_pool_node_t *
711 add_poolhosts(url)
712 char *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
765 ip_pool_node_t *
766 read_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
800 static void
801 setadflen(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 }