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 if (o == NULL) 236 yyerror("sorry, out of memory"); 237 o->o_type = type; 238 o->o_line = yylineNum; 239 o->o_num = 0; 240 o->o_str = (char *)0; 241 return o; 242 } 243 244 static void build_action(olist) 245 opt_t *olist; 246 { 247 action_t *a; 248 opt_t *o; 249 u_32_t m; 250 char c; 251 int i; 252 253 a = (action_t *)calloc(1, sizeof(*a)); 254 if (!a) 255 return; 256 while ((o = olist)) { 257 for (i = 0; macflags[i][0]; i++) 258 if (macflags[i][0] == o->o_type) 259 break; 260 if (macflags[i][1] & a->ac_mflag) { 261 fprintf(stderr, "%s redfined on line %d\n", 262 yykeytostr(o->o_type), yylineNum); 263 if (o->o_str != NULL) 264 free(o->o_str); 265 olist = o->o_next; 266 free(o); 267 continue; 268 } 269 270 a->ac_mflag |= macflags[i][1]; 271 272 switch (o->o_type) 273 { 274 case IPM_DIRECTION : 275 a->ac_direction = o->o_num; 276 break; 277 case IPM_DSTIP : 278 a->ac_dip = o->o_ip.s_addr; 279 for (i = o->o_num, m = 0; i; i--) { 280 m >>= 1; 281 m |= 0x80000000; 282 } 283 a->ac_dmsk = htonl(m); 284 break; 285 case IPM_DSTPORT : 286 a->ac_dport = htons(o->o_num); 287 break; 288 case IPM_EXECUTE : 289 a->ac_exec = o->o_str; 290 c = *o->o_str; 291 if (c== '"'|| c == '\'') { 292 if (o->o_str[strlen(o->o_str) - 1] == c) { 293 a->ac_run = strdup(o->o_str + 1); 294 a->ac_run[strlen(a->ac_run) - 1] ='\0'; 295 } else 296 a->ac_run = o->o_str; 297 } else 298 a->ac_run = o->o_str; 299 o->o_str = NULL; 300 break; 301 case IPM_INTERFACE : 302 a->ac_iface = o->o_str; 303 o->o_str = NULL; 304 break; 305 case IPM_GROUP : 306 if (o->o_str != NULL) 307 strncpy(a->ac_group, o->o_str, FR_GROUPLEN); 308 else 309 sprintf(a->ac_group, "%d", o->o_num); 310 break; 311 case IPM_PACKET : 312 a->ac_packet = o->o_num; 313 break; 314 case IPM_PROTOCOL : 315 a->ac_proto = o->o_num; 316 break; 317 case IPM_RULE : 318 a->ac_rule = o->o_num; 319 break; 320 case IPM_RESULT : 321 if (!strcasecmp(o->o_str, "pass")) 322 a->ac_result = IPMR_PASS; 323 else if (!strcasecmp(o->o_str, "block")) 324 a->ac_result = IPMR_BLOCK; 325 else if (!strcasecmp(o->o_str, "short")) 326 a->ac_result = IPMR_SHORT; 327 else if (!strcasecmp(o->o_str, "nomatch")) 328 a->ac_result = IPMR_NOMATCH; 329 else if (!strcasecmp(o->o_str, "log")) 330 a->ac_result = IPMR_LOG; 331 break; 332 case IPM_SECOND : 333 a->ac_second = o->o_num; 334 break; 335 case IPM_SRCIP : 336 a->ac_sip = o->o_ip.s_addr; 337 for (i = o->o_num, m = 0; i; i--) { 338 m >>= 1; 339 m |= 0x80000000; 340 } 341 a->ac_smsk = htonl(m); 342 break; 343 case IPM_SRCPORT : 344 a->ac_sport = htons(o->o_num); 345 break; 346 case IPM_TAG : 347 a->ac_tag = o->o_num; 348 break; 349 default : 350 break; 351 } 352 353 olist = o->o_next; 354 if (o->o_str != NULL) 355 free(o->o_str); 356 free(o); 357 } 358 a->a_next = alist; 359 alist = a; 360 } 361 362 363 void check_action(buf, opts, log) 364 char *buf; 365 int opts; 366 char *log; 367 { 368 struct timeval tv; 369 ipflog_t *ipf; 370 tcphdr_t *tcp; 371 iplog_t *ipl; 372 action_t *a; 373 u_long t1; 374 ip_t *ip; 375 376 ipl = (iplog_t *)buf; 377 ipf = (ipflog_t *)(ipl +1); 378 ip = (ip_t *)(ipf + 1); 379 tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); 380 381 for (a = alist; a; a = a->a_next) { 382 if (a->ac_mflag & IPMAC_DIRECTION) { 383 if (a->ac_direction == IPM_IN) { 384 if (!(ipf->fl_flags & FR_INQUE)) 385 continue; 386 } else if (a->ac_direction == IPM_OUT) { 387 if (!(ipf->fl_flags & FR_OUTQUE)) 388 continue; 389 } 390 } 391 392 if (a->ac_mflag & IPMAC_EVERY) { 393 gettimeofday(&tv, NULL); 394 t1 = tv.tv_sec - a->ac_lastsec; 395 if (tv.tv_usec <= a->ac_lastusec) 396 t1--; 397 if (a->ac_second) { 398 if (t1 < a->ac_second) 399 continue; 400 a->ac_lastsec = tv.tv_sec; 401 a->ac_lastusec = tv.tv_usec; 402 } 403 404 if (a->ac_packet) { 405 if (!a->ac_pktcnt) 406 a->ac_pktcnt++; 407 else if (a->ac_pktcnt == a->ac_packet) { 408 a->ac_pktcnt = 0; 409 continue; 410 } else { 411 a->ac_pktcnt++; 412 continue; 413 } 414 } 415 } 416 417 if (a->ac_mflag & IPMAC_DSTIP) { 418 if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) 419 continue; 420 } 421 422 if (a->ac_mflag & IPMAC_DSTPORT) { 423 if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) 424 continue; 425 if (tcp->th_dport != a->ac_dport) 426 continue; 427 } 428 429 if (a->ac_mflag & IPMAC_GROUP) { 430 if (strncmp(a->ac_group, ipf->fl_group, 431 FR_GROUPLEN) != 0) 432 continue; 433 } 434 435 if (a->ac_mflag & IPMAC_INTERFACE) { 436 if (strcmp(a->ac_iface, ipf->fl_ifname)) 437 continue; 438 } 439 440 if (a->ac_mflag & IPMAC_PROTOCOL) { 441 if (a->ac_proto != ip->ip_p) 442 continue; 443 } 444 445 if (a->ac_mflag & IPMAC_RESULT) { 446 if (ipf->fl_lflags & FI_SHORT) { 447 if (a->ac_result != IPMR_SHORT) 448 continue; 449 } else if (FR_ISPASS(ipf->fl_flags)) { 450 if (a->ac_result != IPMR_PASS) 451 continue; 452 } else if (FR_ISBLOCK(ipf->fl_flags)) { 453 if (a->ac_result != IPMR_BLOCK) 454 continue; 455 } else if (ipf->fl_flags & FF_LOGNOMATCH) { 456 if (a->ac_result != IPMR_NOMATCH) 457 continue; 458 } else { /* Log only */ 459 if (a->ac_result != IPMR_LOG) 460 continue; 461 } 462 } 463 464 if (a->ac_mflag & IPMAC_RULE) { 465 if (a->ac_rule != ipf->fl_rule) 466 continue; 467 } 468 469 if (a->ac_mflag & IPMAC_SRCIP) { 470 if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) 471 continue; 472 } 473 474 if (a->ac_mflag & IPMAC_SRCPORT) { 475 if (ip->ip_p != IPPROTO_UDP && ip->ip_p != IPPROTO_TCP) 476 continue; 477 if (tcp->th_sport != a->ac_sport) 478 continue; 479 } 480 481 if (a->ac_mflag & IPMAC_TAG) { 482 if (a->ac_tag != ipf->fl_tag) 483 continue; 484 } 485 486 /* 487 * It matched so now execute the command 488 */ 489 if (a->ac_exec) { 490 switch (fork()) 491 { 492 case 0 : 493 { 494 FILE *pi; 495 496 pi = popen(a->ac_run, "w"); 497 if (pi) { 498 fprintf(pi, "%s\n", log); 499 if (opts & OPT_HEXHDR) { 500 dumphex(pi, 0, buf, 501 sizeof(*ipl) + 502 sizeof(*ipf)); 503 } 504 if (opts & OPT_HEXBODY) { 505 dumphex(pi, 0, (char *)ip, 506 ipf->fl_hlen + 507 ipf->fl_plen); 508 } 509 pclose(pi); 510 } 511 exit(1); 512 } 513 case -1 : 514 break; 515 default : 516 break; 517 } 518 } 519 } 520 } 521 522 523 int load_config(file) 524 char *file; 525 { 526 FILE *fp; 527 528 yylineNum = 0; 529 530 (void) yysettab(yywords); 531 532 fp = fopen(file, "r"); 533 if (!fp) { 534 perror("load_config:fopen:"); 535 return -1; 536 } 537 yyin = fp; 538 while (!feof(fp)) 539 yyparse(); 540 fclose(fp); 541 return 0; 542 } 543