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