1 %{ 2 #include "ipf.h" 3 #undef OPT_NAT 4 #undef OPT_VERBOSE 5 #include "ipmon_l.h" 6 #include "ipmon.h" 7 8 #define YYDEBUG 1 9 10 extern void yyerror __P((char *)); 11 extern int yyparse __P((void)); 12 extern int yylex __P((void)); 13 extern int yydebug; 14 extern FILE *yyin; 15 extern int yylineNum; 16 17 typedef struct opt { 18 struct opt *o_next; 19 int o_line; 20 int o_type; 21 int o_num; 22 char *o_str; 23 struct in_addr o_ip; 24 } opt_t; 25 26 static void build_action __P((struct opt *)); 27 static opt_t *new_opt __P((int)); 28 29 static action_t *alist = NULL; 30 %} 31 32 %union { 33 char *str; 34 u_32_t num; 35 struct in_addr addr; 36 struct opt *opt; 37 union i6addr ip6; 38 } 39 40 %token <num> YY_NUMBER YY_HEX 41 %token <str> YY_STR 42 %token YY_COMMENT 43 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 44 %token YY_RANGE_OUT YY_RANGE_IN 45 %token <ip6> YY_IPV6 46 47 %token IPM_ACTION IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT 48 %token IPM_EVERY IPM_EXECUTE IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT 49 %token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE 50 %token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_TAG IPM_YES 51 %type <addr> ipv4 52 %type <opt> direction dstip dstport every execute group interface option 53 %type <opt> options protocol result rule srcip srcport tag 54 55 %% 56 file: line 57 | assign 58 | file line 59 | file assign 60 ; 61 62 line: IPM_ACTION '{' options '}' ';' { build_action($3); resetlexer(); } 63 | IPM_COMMENT 64 ; 65 66 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 67 resetlexer(); 68 free($1); 69 free($3); 70 } 71 ; 72 73 assigning: 74 '=' { yyvarnext = 1; } 75 ; 76 77 options: 78 option { $$ = $1; } 79 | option ',' options { $1->o_next = $3; $$ = $1; } 80 ; 81 82 option: direction { $$ = $1; } 83 | dstip { $$ = $1; } 84 | dstport { $$ = $1; } 85 | every { $$ = $1; } 86 | execute { $$ = $1; } 87 | group { $$ = $1; } 88 | interface { $$ = $1; } 89 | protocol { $$ = $1; } 90 | result { $$ = $1; } 91 | rule { $$ = $1; } 92 | srcip { $$ = $1; } 93 | srcport { $$ = $1; } 94 | tag { $$ = $1; } 95 ; 96 97 direction: 98 IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION); 99 $$->o_num = IPM_IN; } 100 | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION); 101 $$->o_num = IPM_OUT; } 102 ; 103 104 dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP); 105 $$->o_ip = $3; 106 $$->o_num = $5; } 107 ; 108 109 dstport: 110 IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT); 111 $$->o_num = $3; } 112 | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT); 113 $$->o_str = $3; } 114 ; 115 116 every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND); 117 $$->o_num = 1; } 118 | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND); 119 $$->o_num = $2; } 120 | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET); 121 $$->o_num = 1; } 122 | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET); 123 $$->o_num = $2; } 124 ; 125 126 execute: 127 IPM_EXECUTE '=' YY_STR { $$ = new_opt(IPM_EXECUTE); 128 $$->o_str = $3; } 129 ; 130 131 group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP); 132 $$->o_num = $3; } 133 | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP); 134 $$->o_str = $3; } 135 ; 136 137 interface: 138 IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE); 139 $$->o_str = $3; } 140 ; 141 142 protocol: 143 IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL); 144 $$->o_num = $3; } 145 | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL); 146 $$->o_num = getproto($3); 147 free($3); 148 } 149 ; 150 151 result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT); 152 $$->o_str = $3; } 153 ; 154 155 rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE); 156 $$->o_num = YY_NUMBER; } 157 ; 158 159 srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP); 160 $$->o_ip = $3; 161 $$->o_num = $5; } 162 ; 163 164 srcport: 165 IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT); 166 $$->o_num = $3; } 167 | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT); 168 $$->o_str = $3; } 169 ; 170 171 tag: IPM_TAG '=' YY_NUMBER { $$ = new_opt(IPM_TAG); 172 $$->o_num = $3; } 173 ; 174 175 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 176 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 177 yyerror("Invalid octet string for IP address"); 178 return 0; 179 } 180 $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 181 $$.s_addr = htonl($$.s_addr); 182 } 183 %% 184 static struct wordtab yywords[] = { 185 { "action", IPM_ACTION }, 186 { "body", IPM_BODY }, 187 { "direction", IPM_DIRECTION }, 188 { "dstip", IPM_DSTIP }, 189 { "dstport", IPM_DSTPORT }, 190 { "every", IPM_EVERY }, 191 { "execute", IPM_EXECUTE }, 192 { "group", IPM_GROUP }, 193 { "in", IPM_IN }, 194 { "interface", IPM_INTERFACE }, 195 { "no", IPM_NO }, 196 { "out", IPM_OUT }, 197 { "packet", IPM_PACKET }, 198 { "packets", IPM_PACKETS }, 199 { "protocol", IPM_PROTOCOL }, 200 { "result", IPM_RESULT }, 201 { "rule", IPM_RULE }, 202 { "second", IPM_SECOND }, 203 { "seconds", IPM_SECONDS }, 204 { "srcip", IPM_SRCIP }, 205 { "srcport", IPM_SRCPORT }, 206 { "tag", IPM_TAG }, 207 { "yes", IPM_YES }, 208 { NULL, 0 } 209 }; 210 211 static int macflags[15][2] = { 212 { IPM_DIRECTION, IPMAC_DIRECTION }, 213 { IPM_DSTIP, IPMAC_DSTIP }, 214 { IPM_DSTPORT, IPMAC_DSTPORT }, 215 { IPM_EXECUTE, IPMAC_EXECUTE }, 216 { IPM_GROUP, IPMAC_GROUP }, 217 { IPM_INTERFACE, IPMAC_INTERFACE }, 218 { IPM_PACKET, IPMAC_EVERY }, 219 { IPM_PROTOCOL, IPMAC_PROTOCOL }, 220 { IPM_RESULT, IPMAC_RESULT }, 221 { IPM_RULE, IPMAC_RULE }, 222 { IPM_SECOND, IPMAC_EVERY }, 223 { IPM_SRCIP, IPMAC_SRCIP }, 224 { IPM_SRCPORT, IPMAC_SRCPORT }, 225 { IPM_TAG, IPMAC_TAG }, 226 { 0, 0 } 227 }; 228 229 static opt_t *new_opt(type) 230 int type; 231 { 232 opt_t *o; 233 234 o = (opt_t *)malloc(sizeof(*o)); 235 o->o_type = type; 236 o->o_line = yylineNum; 237 o->o_num = 0; 238 o->o_str = (char *)0; 239 return o; 240 } 241 242 static void build_action(olist) 243 opt_t *olist; 244 { 245 action_t *a; 246 opt_t *o; 247 u_32_t m; 248 char c; 249 int i; 250 251 a = (action_t *)calloc(1, sizeof(*a)); 252 if (!a) 253 return; 254 while ((o = olist)) { 255 for (i = 0; macflags[i][0]; i++) 256 if (macflags[i][0] == o->o_type) 257 break; 258 if (macflags[i][1] & a->ac_mflag) { 259 fprintf(stderr, "%s redfined on line %d\n", 260 yykeytostr(o->o_type), yylineNum); 261 if (o->o_str != NULL) 262 free(o->o_str); 263 olist = o->o_next; 264 free(o); 265 continue; 266 } 267 268 a->ac_mflag |= macflags[i][1]; 269 270 switch (o->o_type) 271 { 272 case IPM_DIRECTION : 273 a->ac_direction = o->o_num; 274 break; 275 case IPM_DSTIP : 276 a->ac_dip = o->o_ip.s_addr; 277 for (i = o->o_num, m = 0; i; i--) { 278 m >>= 1; 279 m |= 0x80000000; 280 } 281 a->ac_dmsk = htonl(m); 282 break; 283 case IPM_DSTPORT : 284 a->ac_dport = htons(o->o_num); 285 break; 286 case IPM_EXECUTE : 287 a->ac_exec = o->o_str; 288 c = *o->o_str; 289 if (c== '"'|| c == '\'') { 290 if (o->o_str[strlen(o->o_str) - 1] == c) { 291 a->ac_run = strdup(o->o_str + 1); 292 a->ac_run[strlen(a->ac_run) - 1] ='\0'; 293 } else 294 a->ac_run = o->o_str; 295 } else 296 a->ac_run = o->o_str; 297 o->o_str = NULL; 298 break; 299 case IPM_INTERFACE : 300 a->ac_iface = o->o_str; 301 o->o_str = NULL; 302 break; 303 case IPM_GROUP : 304 if (o->o_str != NULL) 305 strncpy(a->ac_group, o->o_str, FR_GROUPLEN); 306 else 307 sprintf(a->ac_group, "%d", o->o_num); 308 break; 309 case IPM_PACKET : 310 a->ac_packet = o->o_num; 311 break; 312 case IPM_PROTOCOL : 313 a->ac_proto = o->o_num; 314 break; 315 case IPM_RULE : 316 a->ac_rule = o->o_num; 317 break; 318 case IPM_RESULT : 319 if (!strcasecmp(o->o_str, "pass")) 320 a->ac_result = IPMR_PASS; 321 else if (!strcasecmp(o->o_str, "block")) 322 a->ac_result = IPMR_BLOCK; 323 else if (!strcasecmp(o->o_str, "short")) 324 a->ac_result = IPMR_SHORT; 325 else if (!strcasecmp(o->o_str, "nomatch")) 326 a->ac_result = IPMR_NOMATCH; 327 else if (!strcasecmp(o->o_str, "log")) 328 a->ac_result = IPMR_LOG; 329 break; 330 case IPM_SECOND : 331 a->ac_second = o->o_num; 332 break; 333 case IPM_SRCIP : 334 a->ac_sip = o->o_ip.s_addr; 335 for (i = o->o_num, m = 0; i; i--) { 336 m >>= 1; 337 m |= 0x80000000; 338 } 339 a->ac_smsk = htonl(m); 340 break; 341 case IPM_SRCPORT : 342 a->ac_sport = htons(o->o_num); 343 break; 344 case IPM_TAG : 345 a->ac_tag = o->o_num; 346 break; 347 default : 348 break; 349 } 350 351 olist = o->o_next; 352 if (o->o_str != NULL) 353 free(o->o_str); 354 free(o); 355 } 356 a->a_next = alist; 357 alist = a; 358 } 359 360 361 void check_action(buf, opts, log) 362 char *buf; 363 int opts; 364 char *log; 365 { 366 struct timeval tv; 367 ipflog_t *ipf; 368 tcphdr_t *tcp; 369 iplog_t *ipl; 370 action_t *a; 371 u_long t1; 372 ip_t *ip; 373 374 ipl = (iplog_t *)buf; 375 ipf = (ipflog_t *)(ipl +1); 376 ip = (ip_t *)(ipf + 1); 377 tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); 378 379 for (a = alist; a; a = a->a_next) { 380 if (a->ac_mflag & IPMAC_DIRECTION) { 381 if (a->ac_direction == IPM_IN) { 382 if (!(ipf->fl_flags & FR_INQUE)) 383 continue; 384 } else if (a->ac_direction == IPM_OUT) { 385 if (!(ipf->fl_flags & FR_OUTQUE)) 386 continue; 387 } 388 } 389 390 if (a->ac_mflag & IPMAC_EVERY) { 391 gettimeofday(&tv, NULL); 392 t1 = tv.tv_sec - a->ac_lastsec; 393 if (tv.tv_usec <= a->ac_lastusec) 394 t1--; 395 if (a->ac_second) { 396 if (t1 < a->ac_second) 397 continue; 398 a->ac_lastsec = tv.tv_sec; 399 a->ac_lastusec = tv.tv_usec; 400 } 401 402 if (a->ac_packet) { 403 if (!a->ac_pktcnt) 404 a->ac_pktcnt++; 405 else if (a->ac_pktcnt == a->ac_packet) { 406 a->ac_pktcnt = 0; 407 continue; 408 } else { 409 a->ac_pktcnt++; 410 continue; 411 } 412 } 413 } 414 415 if (a->ac_mflag & IPMAC_DSTIP) { 416 if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) 417 continue; 418 } 419 420 if (a->ac_mflag & IPMAC_DSTPORT) { 421 if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) 422 continue; 423 if (tcp->th_dport != a->ac_dport) 424 continue; 425 } 426 427 if (a->ac_mflag & IPMAC_GROUP) { 428 if (strncmp(a->ac_group, ipf->fl_group, 429 FR_GROUPLEN) != 0) 430 continue; 431 } 432 433 if (a->ac_mflag & IPMAC_INTERFACE) { 434 if (strcmp(a->ac_iface, ipf->fl_ifname)) 435 continue; 436 } 437 438 if (a->ac_mflag & IPMAC_PROTOCOL) { 439 if (a->ac_proto != ip->ip_p) 440 continue; 441 } 442 443 if (a->ac_mflag & IPMAC_RESULT) { 444 if (ipf->fl_lflags & FI_SHORT) { 445 if (a->ac_result != IPMR_SHORT) 446 continue; 447 } else if (FR_ISPASS(ipf->fl_flags)) { 448 if (a->ac_result != IPMR_PASS) 449 continue; 450 } else if (FR_ISBLOCK(ipf->fl_flags)) { 451 if (a->ac_result != IPMR_BLOCK) 452 continue; 453 } else if (ipf->fl_flags & FF_LOGNOMATCH) { 454 if (a->ac_result != IPMR_NOMATCH) 455 continue; 456 } else { /* Log only */ 457 if (a->ac_result != IPMR_LOG) 458 continue; 459 } 460 } 461 462 if (a->ac_mflag & IPMAC_RULE) { 463 if (a->ac_rule != ipf->fl_rule) 464 continue; 465 } 466 467 if (a->ac_mflag & IPMAC_SRCIP) { 468 if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) 469 continue; 470 } 471 472 if (a->ac_mflag & IPMAC_SRCPORT) { 473 if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) 474 continue; 475 if (tcp->th_sport != a->ac_sport) 476 continue; 477 } 478 479 if (a->ac_mflag & IPMAC_TAG) { 480 if (a->ac_tag != ipf->fl_tag) 481 continue; 482 } 483 484 /* 485 * It matched so now execute the command 486 */ 487 if (a->ac_exec) { 488 switch (fork()) 489 { 490 case 0 : 491 { 492 FILE *pi; 493 494 pi = popen(a->ac_run, "w"); 495 if (pi) { 496 fprintf(pi, "%s\n", log); 497 if (opts & OPT_HEXHDR) { 498 dumphex(pi, 0, buf, 499 sizeof(*ipl) + 500 sizeof(*ipf)); 501 } 502 if (opts & OPT_HEXBODY) { 503 dumphex(pi, 0, (char *)ip, 504 ipf->fl_hlen + 505 ipf->fl_plen); 506 } 507 pclose(pi); 508 } 509 exit(1); 510 } 511 case -1 : 512 break; 513 default : 514 break; 515 } 516 } 517 } 518 } 519 520 521 int load_config(file) 522 char *file; 523 { 524 FILE *fp; 525 526 yylineNum = 0; 527 528 (void) yysettab(yywords); 529 530 fp = fopen(file, "r"); 531 if (!fp) { 532 perror("load_config:fopen:"); 533 return -1; 534 } 535 yyin = fp; 536 while (!feof(fp)) 537 yyparse(); 538 fclose(fp); 539 return 0; 540 } 541