xref: /illumos-gate/usr/src/cmd/ipf/tools/ippool_y.y (revision d48be21240dfd051b689384ce2b23479d757f2d8)
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 
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 
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