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