]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ipfilter/tools/ipscan_y.y
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ipfilter / tools / ipscan_y.y
1 /*      $FreeBSD$       */
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
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
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
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
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
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
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
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
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
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
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 }