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