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