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