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