]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ipfilter/tools/ipscan_y.y
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ipfilter / tools / ipscan_y.y
1 /*      $FreeBSD$       */
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
20 extern  char    *optarg;
21 extern  void    yyerror __P((char *));
22 extern  int     yyparse __P((void));
23 extern  int     yylex __P((void));
24 extern  int     yydebug;
25 extern  FILE    *yyin;
26 extern  int     yylineNum;
27 extern  void    printbuf __P((char *, int, int));
28
29
30 void            printent __P((ipscan_t *));
31 void            showlist __P((void));
32 int             getportnum __P((char *));
33 struct in_addr  gethostip __P((char *));
34 struct in_addr  combine __P((int, int, int, int));
35 char            **makepair __P((char *, char *));
36 void            addtag __P((char *, char **, char **, struct action *));
37 int             cram __P((char *, char *));
38 void            usage __P((char *));
39 int             main __P((int, char **));
40
41 int             opts = 0;
42 int             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 %%
73 file:   line ';'
74         | assign ';'
75         | file line ';'
76         | file assign ';'
77         | YY_COMMENT
78         ;
79
80 line:   IPSL_START dline
81         | IPSL_STARTGROUP gline
82         | IPSL_CONTENT oline
83         ;
84
85 dline:  cline                                   { resetlexer(); }
86         | sline                                 { resetlexer(); }
87         | csline                                { resetlexer(); }
88         ;
89
90 gline:  YY_STR ':' glist '=' action
91         ;
92
93 oline:  cline
94         | sline
95         | csline
96         ;
97
98 assign: YY_STR assigning YY_STR
99                                                 { set_variable($1, $3);
100                                                   resetlexer();
101                                                   free($1);
102                                                   free($3);
103                                                   yyvarnext = 0;
104                                                 }
105         ;
106
107 assigning:
108         '='                                     { yyvarnext = 1; }
109         ;
110
111 cline:  tag ':' matchup '=' action              { addtag($1, $3, NULL, &$5); }
112         ;
113
114 sline:  tag ':' '(' ')' ',' matchup '=' action  { addtag($1, NULL, $6, &$8); }
115         ;
116
117 csline: tag ':' matchup ',' matchup '=' action  { addtag($1, $3, $5, &$7); }
118         ;
119
120 glist:  YY_STR
121         | glist ',' YY_STR
122         ;
123
124 tag:    YY_STR                                  { $$ = $1; }
125         ;
126
127 matchup:
128         onehalf                                 { $$ = $1; }
129         | twohalves                             { $$ = $1; }
130         ;
131
132 action: 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
147 result: 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
154 onehalf:
155         '(' YY_STR ')'                  { $$ = makepair($2, NULL); }
156         ;
157
158 twohalves:
159         '(' YY_STR ',' YY_STR ')'       { $$ = makepair($2, $4); }
160         ;
161
162 redirect:
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
171 ipaddr: 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
178 portnum:
179         YY_NUMBER                               { $$ = htons($1); }
180         | YY_STR                                { $$ = getportnum($1);
181                                                   free($1);
182                                                 }
183         ;
184
185 %%
186
187
188 static  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
200 int cram(dst, src)
201 char *dst;
202 char *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
259 void printent(isc)
260 ipscan_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
337 void addtag(tstr, cp, sp, act)
338 char *tstr;
339 char **cp, **sp;
340 struct 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
409 char **makepair(s1, s2)
410 char *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
421 struct in_addr combine(a1, a2, a3, a4)
422 int 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
439 struct in_addr gethostip(host)
440 char *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
455 int getportnum(port)
456 char *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
467 void 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
493 void usage(prog)
494 char *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
502 int main(argc, argv)
503 int argc;
504 char *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 }