ipscan_y.y revision 145510
1/*	$NetBSD$	*/
2
3%{
4#include <sys/types.h>
5#include <sys/ioctl.h>
6#include "ipf.h"
7#include "opts.h"
8#include "kmem.h"
9#include "ipscan_l.h"
10#include "netinet/ip_scan.h"
11
12#define	YYDEBUG	1
13
14extern	char	*optarg;
15extern	void	yyerror __P((char *));
16extern	int	yyparse __P((void));
17extern	int	yylex __P((void));
18extern	int	yydebug;
19extern	FILE	*yyin;
20extern	int	yylineNum;
21extern	void	printbuf __P((char *, int, int));
22
23
24void		printent __P((ipscan_t *));
25void		showlist __P((void));
26int		getportnum __P((char *));
27struct in_addr	gethostip __P((char *));
28struct in_addr	combine __P((int, int, int, int));
29char		**makepair __P((char *, char *));
30void		addtag __P((char *, char **, char **, struct action *));
31int		cram __P((char *, char *));
32void		usage __P((char *));
33int		main __P((int, char **));
34
35int		opts = 0;
36int		fd = -1;
37
38
39%}
40
41%union	{
42	char	*str;
43	char	**astr;
44	u_32_t	num;
45	struct	in_addr	ipa;
46	struct	action	act;
47	union	i6addr	ip6;
48}
49
50%type	<str> tag
51%type	<act> action redirect result
52%type	<ipa> ipaddr
53%type	<num> portnum
54%type	<astr> matchup onehalf twohalves
55
56%token  <num>   YY_NUMBER YY_HEX
57%token  <str>   YY_STR
58%token          YY_COMMENT
59%token          YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
60%token          YY_RANGE_OUT YY_RANGE_IN
61%token  <ip6>   YY_IPV6
62%token		IPSL_START IPSL_STARTGROUP IPSL_CONTENT
63
64%token	IPSL_CLOSE IPSL_TRACK IPSL_EOF IPSL_REDIRECT IPSL_ELSE
65
66%%
67file:	line ';'
68	| assign ';'
69	| file line ';'
70	| file assign ';'
71	| YY_COMMENT
72	;
73
74line:	IPSL_START dline
75	| IPSL_STARTGROUP gline
76	| IPSL_CONTENT oline
77	;
78
79dline:	cline					{ resetlexer(); }
80	| sline					{ resetlexer(); }
81	| csline				{ resetlexer(); }
82	;
83
84gline:	YY_STR ':' glist '=' action
85	;
86
87oline:	cline
88	| sline
89	| csline
90	;
91
92assign:	YY_STR assigning YY_STR
93						{ set_variable($1, $3);
94						  resetlexer();
95						  free($1);
96						  free($3);
97						}
98	;
99
100assigning:
101	'='					{ yyvarnext = 1; }
102	;
103
104cline:	tag ':' matchup '=' action		{ addtag($1, $3, NULL, &$5); }
105	;
106
107sline:	tag ':' '(' ')' ',' matchup '=' action	{ addtag($1, NULL, $6, &$8); }
108	;
109
110csline:	tag ':' matchup ',' matchup '=' action	{ addtag($1, $3, $5, &$7); }
111	;
112
113glist:	YY_STR
114	| glist ',' YY_STR
115	;
116
117tag:	YY_STR					{ $$ = $1; }
118	;
119
120matchup:
121	onehalf					{ $$ = $1; }
122	| twohalves				{ $$ = $1; }
123	;
124
125action:	result				{ $$.act_val = $1.act_val;
126					  $$.act_ip = $1.act_ip;
127					  $$.act_port = $1.act_port; }
128	| result IPSL_ELSE result	{ $$.act_val = $1.act_val;
129					  $$.act_else = $3.act_val;
130					  if ($1.act_val == IPSL_REDIRECT) {
131						  $$.act_ip = $1.act_ip;
132						  $$.act_port = $1.act_port;
133					  }
134					  if ($3.act_val == IPSL_REDIRECT) {
135						  $$.act_eip = $3.act_eip;
136						  $$.act_eport = $3.act_eport;
137					  }
138					}
139
140result:	IPSL_CLOSE				{ $$.act_val = IPSL_CLOSE; }
141	| IPSL_TRACK				{ $$.act_val = IPSL_TRACK; }
142	| redirect				{ $$.act_val = IPSL_REDIRECT;
143						  $$.act_ip = $1.act_ip;
144						  $$.act_port = $1.act_port; }
145	;
146
147onehalf:
148	'(' YY_STR ')'			{ $$ = makepair($2, NULL); }
149	;
150
151twohalves:
152	'(' YY_STR ',' YY_STR ')'	{ $$ = makepair($2, $4); }
153	;
154
155redirect:
156	IPSL_REDIRECT '(' ipaddr ')'		{ $$.act_ip = $3;
157						  $$.act_port = 0; }
158	| IPSL_REDIRECT '(' ipaddr ',' portnum ')'
159						{ $$.act_ip = $3;
160						  $$.act_port = $5; }
161	;
162
163
164ipaddr:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
165						{ $$ = combine($1,$3,$5,$7); }
166	| YY_STR				{ $$ = gethostip($1);
167						  free($1);
168						}
169	;
170
171portnum:
172	YY_NUMBER				{ $$ = htons($1); }
173	| YY_STR				{ $$ = getportnum($1);
174						  free($1);
175						}
176	;
177
178%%
179
180
181static	struct	wordtab	yywords[] = {
182	{ "close",		IPSL_CLOSE },
183	{ "content",		IPSL_CONTENT },
184	{ "else",		IPSL_ELSE },
185	{ "start-group",	IPSL_STARTGROUP },
186	{ "redirect",		IPSL_REDIRECT },
187	{ "start",		IPSL_START },
188	{ "track",		IPSL_TRACK },
189	{ NULL,		0 }
190};
191
192
193int cram(dst, src)
194char *dst;
195char *src;
196{
197	char c, *s, *t, *u;
198	int i, j, k;
199
200	c = *src;
201	s = src + 1;
202	t = strchr(s, c);
203	*t = '\0';
204	for (u = dst, i = 0; (i <= ISC_TLEN) && (s < t); ) {
205		c = *s++;
206		if (c == '\\') {
207			if (s >= t)
208				break;
209			j = k = 0;
210			do {
211				c = *s++;
212				if (j && (!ISDIGIT(c) || (c > '7') ||
213				     (k >= 248))) {
214					*u++ = k, i++;
215					j = k = 0;
216					s--;
217					break;
218				}
219				i++;
220
221				if (ISALPHA(c) || (c > '7')) {
222					switch (c)
223					{
224					case 'n' :
225						*u++ = '\n';
226						break;
227					case 'r' :
228						*u++ = '\r';
229						break;
230					case 't' :
231						*u++ = '\t';
232						break;
233					default :
234						*u++ = c;
235						break;
236					}
237				} else if (ISDIGIT(c)) {
238					j = 1;
239					k <<= 3;
240					k |= (c - '0');
241					i--;
242				} else
243						*u++ = c;
244			} while ((i <= ISC_TLEN) && (s <= t) && (j > 0));
245		} else
246			*u++ = c, i++;
247	}
248	return i;
249}
250
251
252void printent(isc)
253ipscan_t *isc;
254{
255	char buf[ISC_TLEN+1];
256	u_char *u;
257	int i, j;
258
259	buf[ISC_TLEN] = '\0';
260	bcopy(isc->ipsc_ctxt, buf, ISC_TLEN);
261	printf("%s : (\"", isc->ipsc_tag);
262	printbuf(isc->ipsc_ctxt, isc->ipsc_clen, 0);
263
264	bcopy(isc->ipsc_cmsk, buf, ISC_TLEN);
265	printf("\", \"%s\"), (\"", buf);
266
267	printbuf(isc->ipsc_stxt, isc->ipsc_slen, 0);
268
269	bcopy(isc->ipsc_smsk, buf, ISC_TLEN);
270	printf("\", \"%s\") = ", buf);
271
272	switch (isc->ipsc_action)
273	{
274	case ISC_A_TRACK :
275		printf("track");
276		break;
277	case ISC_A_REDIRECT :
278		printf("redirect");
279		printf("(%s", inet_ntoa(isc->ipsc_ip));
280		if (isc->ipsc_port)
281			printf(",%d", isc->ipsc_port);
282		printf(")");
283		break;
284	case ISC_A_CLOSE :
285		printf("close");
286		break;
287	default :
288		break;
289	}
290
291	if (isc->ipsc_else != ISC_A_NONE) {
292		printf(" else ");
293		switch (isc->ipsc_else)
294		{
295		case ISC_A_TRACK :
296			printf("track");
297			break;
298		case ISC_A_REDIRECT :
299			printf("redirect");
300			printf("(%s", inet_ntoa(isc->ipsc_eip));
301			if (isc->ipsc_eport)
302				printf(",%d", isc->ipsc_eport);
303			printf(")");
304			break;
305		case ISC_A_CLOSE :
306			printf("close");
307			break;
308		default :
309			break;
310		}
311	}
312	printf("\n");
313
314	if (opts & OPT_DEBUG) {
315		for (u = (u_char *)isc, i = sizeof(*isc); i; ) {
316			printf("#");
317			for (j = 32; (j > 0) && (i > 0); j--, i--)
318				printf("%s%02x", (j & 7) ? "" : " ", *u++);
319			printf("\n");
320		}
321	}
322	if (opts & OPT_VERBOSE) {
323		printf("# hits %d active %d fref %d sref %d\n",
324			isc->ipsc_hits, isc->ipsc_active, isc->ipsc_fref,
325			isc->ipsc_sref);
326	}
327}
328
329
330void addtag(tstr, cp, sp, act)
331char *tstr;
332char **cp, **sp;
333struct action *act;
334{
335	ipscan_t isc, *iscp;
336
337	bzero((char *)&isc, sizeof(isc));
338
339	strncpy(isc.ipsc_tag, tstr, sizeof(isc.ipsc_tag));
340	isc.ipsc_tag[sizeof(isc.ipsc_tag) - 1] = '\0';
341
342	if (cp) {
343		isc.ipsc_clen = cram(isc.ipsc_ctxt, cp[0]);
344		if (cp[1]) {
345			if (cram(isc.ipsc_cmsk, cp[1]) != isc.ipsc_clen) {
346				fprintf(stderr,
347					"client text/mask strings different length\n");
348				return;
349			}
350		}
351	}
352
353	if (sp) {
354		isc.ipsc_slen = cram(isc.ipsc_stxt, sp[0]);
355		if (sp[1]) {
356			if (cram(isc.ipsc_smsk, sp[1]) != isc.ipsc_slen) {
357				fprintf(stderr,
358					"server text/mask strings different length\n");
359				return;
360			}
361		}
362	}
363
364	if (act->act_val == IPSL_CLOSE) {
365		isc.ipsc_action = ISC_A_CLOSE;
366	} else if (act->act_val == IPSL_TRACK) {
367		isc.ipsc_action = ISC_A_TRACK;
368	} else if (act->act_val == IPSL_REDIRECT) {
369		isc.ipsc_action = ISC_A_REDIRECT;
370		isc.ipsc_ip = act->act_ip;
371		isc.ipsc_port = act->act_port;
372		fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1);
373	}
374
375	if (act->act_else == IPSL_CLOSE) {
376		isc.ipsc_else = ISC_A_CLOSE;
377	} else if (act->act_else == IPSL_TRACK) {
378		isc.ipsc_else = ISC_A_TRACK;
379	} else if (act->act_else == IPSL_REDIRECT) {
380		isc.ipsc_else = ISC_A_REDIRECT;
381		isc.ipsc_eip = act->act_eip;
382		isc.ipsc_eport = act->act_eport;
383		fprintf(stderr, "%d: redirect unsupported\n", yylineNum + 1);
384	}
385
386	if (!(opts & OPT_DONOTHING)) {
387		iscp = &isc;
388		if (opts & OPT_REMOVE) {
389			if (ioctl(fd, SIOCRMSCA, &iscp) == -1)
390				perror("SIOCADSCA");
391		} else {
392			if (ioctl(fd, SIOCADSCA, &iscp) == -1)
393				perror("SIOCADSCA");
394		}
395	}
396
397	if (opts & OPT_VERBOSE)
398		printent(&isc);
399}
400
401
402char **makepair(s1, s2)
403char *s1, *s2;
404{
405	char **a;
406
407	a = malloc(sizeof(char *) * 2);
408	a[0] = s1;
409	a[1] = s2;
410	return a;
411}
412
413
414struct in_addr combine(a1, a2, a3, a4)
415int a1, a2, a3, a4;
416{
417	struct in_addr in;
418
419	a1 &= 0xff;
420	in.s_addr = a1 << 24;
421	a2 &= 0xff;
422	in.s_addr |= (a2 << 16);
423	a3 &= 0xff;
424	in.s_addr |= (a3 << 8);
425	a4 &= 0xff;
426	in.s_addr |= a4;
427	in.s_addr = htonl(in.s_addr);
428	return in;
429}
430
431
432struct in_addr gethostip(host)
433char *host;
434{
435	struct hostent *hp;
436	struct in_addr in;
437
438	in.s_addr = 0;
439
440	hp = gethostbyname(host);
441	if (!hp)
442		return in;
443	bcopy(hp->h_addr, (char *)&in, sizeof(in));
444	return in;
445}
446
447
448int getportnum(port)
449char *port;
450{
451	struct servent *s;
452
453	s = getservbyname(port, "tcp");
454	if (s == NULL)
455		return -1;
456	return s->s_port;
457}
458
459
460void showlist()
461{
462	ipscanstat_t ipsc, *ipscp = &ipsc;
463	ipscan_t isc;
464
465	if (ioctl(fd, SIOCGSCST, &ipscp) == -1)
466		perror("ioctl(SIOCGSCST)");
467	else if (opts & OPT_SHOWLIST) {
468		while (ipsc.iscs_list != NULL) {
469			if (kmemcpy((char *)&isc, (u_long)ipsc.iscs_list,
470				    sizeof(isc)) == -1) {
471				perror("kmemcpy");
472				break;
473			} else {
474				printent(&isc);
475				ipsc.iscs_list = isc.ipsc_next;
476			}
477		}
478	} else {
479		printf("scan entries loaded\t%d\n", ipsc.iscs_entries);
480		printf("scan entries matches\t%ld\n", ipsc.iscs_acted);
481		printf("negative matches\t%ld\n", ipsc.iscs_else);
482	}
483}
484
485
486void usage(prog)
487char *prog;
488{
489	fprintf(stderr, "Usage:\t%s [-dnrv] -f <filename>\n", prog);
490	fprintf(stderr, "\t%s [-dlv]\n", prog);
491	exit(1);
492}
493
494
495int main(argc, argv)
496int argc;
497char *argv[];
498{
499	FILE *fp = NULL;
500	int c;
501
502	(void) yysettab(yywords);
503
504	if (argc < 2)
505		usage(argv[0]);
506
507	while ((c = getopt(argc, argv, "df:lnrsv")) != -1)
508		switch (c)
509		{
510		case 'd' :
511			opts |= OPT_DEBUG;
512			yydebug++;
513			break;
514		case 'f' :
515			if (!strcmp(optarg, "-"))
516				fp = stdin;
517			else {
518				fp = fopen(optarg, "r");
519				if (!fp) {
520					perror("open");
521					exit(1);
522				}
523			}
524			yyin = fp;
525			break;
526		case 'l' :
527			opts |= OPT_SHOWLIST;
528			break;
529		case 'n' :
530			opts |= OPT_DONOTHING;
531			break;
532		case 'r' :
533			opts |= OPT_REMOVE;
534			break;
535		case 's' :
536			opts |= OPT_STAT;
537			break;
538		case 'v' :
539			opts |= OPT_VERBOSE;
540			break;
541		}
542
543	if (!(opts & OPT_DONOTHING)) {
544		fd = open(IPL_SCAN, O_RDWR);
545		if (fd == -1) {
546			perror("open(IPL_SCAN)");
547			exit(1);
548		}
549	}
550
551	if (fp != NULL) {
552		yylineNum = 1;
553
554		while (!feof(fp))
555			yyparse();
556		fclose(fp);
557		exit(0);
558	}
559
560	if (opts & (OPT_SHOWLIST|OPT_STAT)) {
561		showlist();
562		exit(0);
563	}
564	exit(1);
565}
566