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