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