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