]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ipfilter/tools/ippool_y.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ipfilter / tools / ippool_y.y
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2001-2006 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  */
8 %{
9 #include <sys/types.h>
10 #include <sys/time.h>
11 #include <sys/param.h>
12 #include <sys/socket.h>
13 #if defined(BSD) && (BSD >= 199306)
14 # include <sys/cdefs.h>
15 #endif
16 #include <sys/ioctl.h>
17
18 #include <net/if.h>
19 #if __FreeBSD_version >= 300000
20 # include <net/if_var.h>
21 #endif
22 #include <netinet/in.h>
23
24 #include <arpa/inet.h>
25
26 #include <stdio.h>
27 #include <fcntl.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <netdb.h>
31 #include <ctype.h>
32 #include <unistd.h>
33
34 #include "ipf.h"
35 #include "netinet/ip_lookup.h"
36 #include "netinet/ip_pool.h"
37 #include "netinet/ip_htable.h"
38 #include "ippool_l.h"
39 #include "kmem.h"
40
41 #define YYDEBUG 1
42 #define YYSTACKSIZE     0x00ffffff
43
44 extern  int     yyparse __P((void));
45 extern  int     yydebug;
46 extern  FILE    *yyin;
47
48 static  iphtable_t      ipht;
49 static  iphtent_t       iphte;
50 static  ip_pool_t       iplo;
51 static  ioctlfunc_t     poolioctl = NULL;
52 static  char            poolname[FR_GROUPLEN];
53
54 static iphtent_t *add_htablehosts __P((char *));
55 static ip_pool_node_t *add_poolhosts __P((char *));
56
57 %}
58
59 %union  {
60         char    *str;
61         u_32_t  num;
62         struct  in_addr addr;
63         struct  alist_s *alist;
64         struct  in_addr adrmsk[2];
65         iphtent_t       *ipe;
66         ip_pool_node_t  *ipp;
67         union   i6addr  ip6;
68 }
69
70 %token  <num>   YY_NUMBER YY_HEX
71 %token  <str>   YY_STR
72 %token    YY_COMMENT 
73 %token    YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
74 %token    YY_RANGE_OUT YY_RANGE_IN
75 %token  <ip6>   YY_IPV6
76
77 %token  IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT
78 %token  IPT_TABLE IPT_GROUPMAP IPT_HASH
79 %token  IPT_ROLE IPT_TYPE IPT_TREE
80 %token  IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME
81 %type   <num> role table inout
82 %type   <ipp> ipftree range addrlist
83 %type   <adrmsk> addrmask
84 %type   <ipe> ipfgroup ipfhash hashlist hashentry
85 %type   <ipe> groupentry setgrouplist grouplist
86 %type   <addr> ipaddr mask ipv4
87 %type   <str> number setgroup
88
89 %%
90 file:   line
91         | assign
92         | file line
93         | file assign
94         ;
95
96 line:   table role ipftree eol          { iplo.ipo_unit = $2;
97                                           iplo.ipo_list = $3;
98                                           load_pool(&iplo, poolioctl);
99                                           resetlexer();
100                                         }
101         | table role ipfhash eol        { ipht.iph_unit = $2;
102                                           ipht.iph_type = IPHASH_LOOKUP;
103                                           load_hash(&ipht, $3, poolioctl);
104                                           resetlexer();
105                                         }
106         | groupmap role number ipfgroup eol
107                                         { ipht.iph_unit = $2;
108                                           strncpy(ipht.iph_name, $3,
109                                                   sizeof(ipht.iph_name));
110                                           ipht.iph_type = IPHASH_GROUPMAP;
111                                           load_hash(&ipht, $4, poolioctl);
112                                           resetlexer();
113                                         }
114         | YY_COMMENT
115         ;
116
117 eol:    ';'
118         ;
119
120 assign: YY_STR assigning YY_STR ';'     { set_variable($1, $3);
121                                           resetlexer();
122                                           free($1);
123                                           free($3);
124                                           yyvarnext = 0;
125                                         }
126         ;
127
128 assigning:
129         '='                             { yyvarnext = 1; }
130         ;
131
132 table:  IPT_TABLE               { bzero((char *)&ipht, sizeof(ipht));
133                                   bzero((char *)&iphte, sizeof(iphte));
134                                   bzero((char *)&iplo, sizeof(iplo));
135                                   *ipht.iph_name = '\0';
136                                   iplo.ipo_flags = IPHASH_ANON;
137                                   iplo.ipo_name[0] = '\0';
138                                 }
139         ;
140
141 groupmap:
142         IPT_GROUPMAP inout      { bzero((char *)&ipht, sizeof(ipht));
143                                   bzero((char *)&iphte, sizeof(iphte));
144                                   *ipht.iph_name = '\0';
145                                   ipht.iph_unit = IPHASH_GROUPMAP;
146                                   ipht.iph_flags = $2;
147                                 }
148         ;
149
150 inout:  IPT_IN                          { $$ = FR_INQUE; }
151         | IPT_OUT                       { $$ = FR_OUTQUE; }
152         ;
153 role:
154         IPT_ROLE '=' IPT_IPF            { $$ = IPL_LOGIPF; }
155         | IPT_ROLE '=' IPT_NAT          { $$ = IPL_LOGNAT; }
156         | IPT_ROLE '=' IPT_AUTH         { $$ = IPL_LOGAUTH; }
157         | IPT_ROLE '=' IPT_COUNT        { $$ = IPL_LOGCOUNT; }
158         ;
159
160 ipftree:
161         IPT_TYPE '=' IPT_TREE number start addrlist end
162                                         { strncpy(iplo.ipo_name, $4,
163                                                   sizeof(iplo.ipo_name));
164                                           $$ = $6;
165                                         }
166         ;
167
168 ipfhash:
169         IPT_TYPE '=' IPT_HASH number hashopts start hashlist end
170                                         { strncpy(ipht.iph_name, $4,
171                                                   sizeof(ipht.iph_name));
172                                           $$ = $7;
173                                         }
174         ;
175
176 ipfgroup:
177         setgroup hashopts start grouplist end
178                                         { iphtent_t *e;
179                                           for (e = $4; e != NULL;
180                                                e = e->ipe_next)
181                                                 if (e->ipe_group[0] == '\0')
182                                                         strncpy(e->ipe_group,
183                                                                 $1,
184                                                                 FR_GROUPLEN);
185                                           $$ = $4;
186                                         }
187         | hashopts start setgrouplist end               { $$ = $3; }
188         ;
189
190 number: IPT_NUM '=' YY_NUMBER                   { sprintf(poolname, "%u", $3);
191                                                   $$ = poolname;
192                                                 }
193         | IPT_NAME '=' YY_STR                   { $$ = $3; }
194         |                                       { $$ = ""; }
195         ;
196
197 setgroup:
198         IPT_GROUP '=' YY_STR            { char tmp[FR_GROUPLEN+1];
199                                           strncpy(tmp, $3, FR_GROUPLEN);
200                                           $$ = strdup(tmp);
201                                         }
202         | IPT_GROUP '=' YY_NUMBER       { char tmp[FR_GROUPLEN+1];
203                                           sprintf(tmp, "%u", $3);
204                                           $$ = strdup(tmp);
205                                         }
206         ;
207
208 hashopts:
209         | size
210         | seed
211         | size seed
212         ;
213
214 addrlist:
215         next                            { $$ = NULL; }
216         | range next addrlist           { $1->ipn_next = $3; $$ = $1; }
217         | range next                    { $$ = $1; }
218         ;
219
220 grouplist:
221         next                            { $$ = NULL; }
222         | groupentry next grouplist     { $$ = $1; $1->ipe_next = $3; }
223         | addrmask next grouplist       { $$ = calloc(1, sizeof(iphtent_t));
224                                           bcopy((char *)&($1[0]),
225                                                 (char *)&($$->ipe_addr),
226                                                 sizeof($$->ipe_addr));
227                                           bcopy((char *)&($1[1]),
228                                                 (char *)&($$->ipe_mask),
229                                                 sizeof($$->ipe_mask));
230                                           $$->ipe_next = $3;
231                                         }
232         | groupentry next               { $$ = $1; }
233         | addrmask next                 { $$ = calloc(1, sizeof(iphtent_t));
234                                           bcopy((char *)&($1[0]),
235                                                 (char *)&($$->ipe_addr),
236                                                 sizeof($$->ipe_addr));
237                                           bcopy((char *)&($1[1]),
238                                                 (char *)&($$->ipe_mask),
239                                                 sizeof($$->ipe_mask));
240                                         }
241         ;
242
243 setgrouplist:
244         next                            { $$ = NULL; }
245         | groupentry next               { $$ = $1; }
246         | groupentry next setgrouplist  { $1->ipe_next = $3; $$ = $1; }
247         ;
248
249 groupentry:
250         addrmask ',' setgroup           { $$ = calloc(1, sizeof(iphtent_t));
251                                           bcopy((char *)&($1[0]),
252                                                 (char *)&($$->ipe_addr),
253                                                 sizeof($$->ipe_addr));
254                                           bcopy((char *)&($1[1]),
255                                                 (char *)&($$->ipe_mask),
256                                                 sizeof($$->ipe_mask));
257                                           strncpy($$->ipe_group, $3,
258                                                   FR_GROUPLEN);
259                                           free($3);
260                                         }
261         | YY_STR                        { $$ = add_htablehosts($1); }
262         ;
263
264 range:  addrmask        { $$ = calloc(1, sizeof(*$$));
265                           $$->ipn_info = 0;
266                           $$->ipn_addr.adf_len = sizeof($$->ipn_addr);
267                           $$->ipn_addr.adf_addr.in4.s_addr = $1[0].s_addr;
268                           $$->ipn_mask.adf_len = sizeof($$->ipn_mask);
269                           $$->ipn_mask.adf_addr.in4.s_addr = $1[1].s_addr;
270                         }
271         | '!' addrmask  { $$ = calloc(1, sizeof(*$$));
272                           $$->ipn_info = 1;
273                           $$->ipn_addr.adf_len = sizeof($$->ipn_addr);
274                           $$->ipn_addr.adf_addr.in4.s_addr = $2[0].s_addr;
275                           $$->ipn_mask.adf_len = sizeof($$->ipn_mask);
276                           $$->ipn_mask.adf_addr.in4.s_addr = $2[1].s_addr;
277                         }
278         | YY_STR                        { $$ = add_poolhosts($1); }
279
280 hashlist:
281         next                            { $$ = NULL; }
282         | hashentry next                { $$ = $1; }
283         | hashentry next hashlist       { $1->ipe_next = $3; $$ = $1; }
284         ;
285
286 hashentry:
287         addrmask                        { $$ = calloc(1, sizeof(iphtent_t));
288                                           bcopy((char *)&($1[0]),
289                                                 (char *)&($$->ipe_addr),
290                                                 sizeof($$->ipe_addr));
291                                           bcopy((char *)&($1[1]),
292                                                 (char *)&($$->ipe_mask),
293                                                 sizeof($$->ipe_mask));
294                                         }
295         | YY_STR                        { $$ = add_htablehosts($1); }
296         ;
297
298 addrmask:
299         ipaddr '/' mask         { $$[0] = $1; $$[1].s_addr = $3.s_addr;
300                                   yyexpectaddr = 0;
301                                 }
302         | ipaddr                { $$[0] = $1; $$[1].s_addr = 0xffffffff;
303                                   yyexpectaddr = 0;
304                                 }
305         ;
306
307 ipaddr: ipv4                    { $$ = $1; }
308         | YY_NUMBER             { $$.s_addr = htonl($1); }
309         ;
310
311 mask:   YY_NUMBER               { ntomask(4, $1, (u_32_t *)&$$.s_addr); }
312         | ipv4                  { $$ = $1; }
313         ;
314
315 start:  '{'                     { yyexpectaddr = 1; }
316         ;
317
318 end:    '}'                     { yyexpectaddr = 0; }
319         ;
320
321 next:   ';'                     { yyexpectaddr = 1; }
322         ;
323
324 size:   IPT_SIZE '=' YY_NUMBER  { ipht.iph_size = $3; }
325         ;
326
327 seed:   IPT_SEED '=' YY_NUMBER  { ipht.iph_seed = $3; }
328         ;
329
330 ipv4:   YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
331                 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
332                         yyerror("Invalid octet string for IP address");
333                         return 0;
334                   }
335                   $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
336                   $$.s_addr = htonl($$.s_addr);
337                 }
338         ;
339 %%
340 static  wordtab_t       yywords[] = {
341         { "auth",       IPT_AUTH },
342         { "count",      IPT_COUNT },
343         { "group",      IPT_GROUP },
344         { "group-map",  IPT_GROUPMAP },
345         { "hash",       IPT_HASH },
346         { "in",         IPT_IN },
347         { "ipf",        IPT_IPF },
348         { "name",       IPT_NAME },
349         { "nat",        IPT_NAT },
350         { "number",     IPT_NUM },
351         { "out",        IPT_OUT },
352         { "role",       IPT_ROLE },
353         { "seed",       IPT_SEED },
354         { "size",       IPT_SIZE },
355         { "table",      IPT_TABLE },
356         { "tree",       IPT_TREE },
357         { "type",       IPT_TYPE },
358         { NULL,         0 }
359 };
360
361
362 int ippool_parsefile(fd, filename, iocfunc)
363 int fd;
364 char *filename;
365 ioctlfunc_t iocfunc;
366 {
367         FILE *fp = NULL;
368         char *s;
369
370         yylineNum = 1;
371         (void) yysettab(yywords);
372
373         s = getenv("YYDEBUG");
374         if (s)
375                 yydebug = atoi(s);
376         else
377                 yydebug = 0;
378
379         if (strcmp(filename, "-")) {
380                 fp = fopen(filename, "r");
381                 if (!fp) {
382                         fprintf(stderr, "fopen(%s) failed: %s\n", filename,
383                                 STRERROR(errno));
384                         return -1;
385                 }
386         } else
387                 fp = stdin;
388
389         while (ippool_parsesome(fd, fp, iocfunc) == 1)
390                 ;
391         if (fp != NULL)
392                 fclose(fp);
393         return 0;
394 }
395
396
397 int ippool_parsesome(fd, fp, iocfunc)
398 int fd;
399 FILE *fp;
400 ioctlfunc_t iocfunc;
401 {
402         char *s;
403         int i;
404
405         poolioctl = iocfunc;
406
407         if (feof(fp))
408                 return 0;
409         i = fgetc(fp);
410         if (i == EOF)
411                 return 0;
412         if (ungetc(i, fp) == EOF)
413                 return 0;
414         if (feof(fp))
415                 return 0;
416         s = getenv("YYDEBUG");
417         if (s)
418                 yydebug = atoi(s);
419         else
420                 yydebug = 0;
421
422         yyin = fp;
423         yyparse();
424         return 1;
425 }
426
427
428 static iphtent_t *
429 add_htablehosts(url)
430 char *url;
431 {
432         iphtent_t *htop, *hbot, *h;
433         alist_t *a, *hlist;
434
435         if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
436                 hlist = load_url(url);
437         } else {
438                 use_inet6 = 0;
439
440                 hlist = calloc(1, sizeof(*hlist));
441                 if (hlist == NULL)
442                         return NULL;
443
444                 if (gethost(url, &hlist->al_addr) == -1)
445                         yyerror("Unknown hostname");
446         }
447
448         hbot = NULL;
449         htop = NULL;
450
451         for (a = hlist; a != NULL; a = a->al_next) {
452                 h = calloc(1, sizeof(*h));
453                 if (h == NULL)
454                         break;
455
456                 bcopy((char *)&a->al_addr, (char *)&h->ipe_addr,
457                       sizeof(h->ipe_addr));
458                 bcopy((char *)&a->al_mask, (char *)&h->ipe_mask,
459                       sizeof(h->ipe_mask));
460
461                 if (hbot != NULL)
462                         hbot->ipe_next = h;
463                 else
464                         htop = h;
465                 hbot = h;
466         }
467
468         alist_free(hlist);
469
470         return htop;
471 }
472
473
474 static ip_pool_node_t *
475 add_poolhosts(url)
476 char *url;
477 {
478         ip_pool_node_t *ptop, *pbot, *p;
479         alist_t *a, *hlist;
480
481         if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
482                 hlist = load_url(url);
483         } else {
484                 use_inet6 = 0;
485
486                 hlist = calloc(1, sizeof(*hlist));
487                 if (hlist == NULL)
488                         return NULL;
489
490                 if (gethost(url, &hlist->al_addr) == -1)
491                         yyerror("Unknown hostname");
492         }
493
494         pbot = NULL;
495         ptop = NULL;
496
497         for (a = hlist; a != NULL; a = a->al_next) {
498                 p = calloc(1, sizeof(*p));
499                 if (p == NULL)
500                         break;
501
502                 p->ipn_addr.adf_len = 8;
503                 p->ipn_mask.adf_len = 8;
504
505                 p->ipn_info = a->al_not;
506
507                 bcopy((char *)&a->al_addr, (char *)&p->ipn_addr.adf_addr,
508                       sizeof(p->ipn_addr.adf_addr));
509                 bcopy((char *)&a->al_mask, (char *)&p->ipn_mask.adf_addr,
510                       sizeof(p->ipn_mask.adf_addr));
511
512                 if (pbot != NULL)
513                         pbot->ipn_next = p;
514                 else
515                         ptop = p;
516                 pbot = p;
517         }
518
519         alist_free(hlist);
520
521         return ptop;
522 }