1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 #include "ipf.h" 9 #include "ipmon.h" 10 #include <sys/ioctl.h> 11 #include <sys/stat.h> 12 #include <syslog.h> 13 #include <ctype.h> 14 #include <fcntl.h> 15 #include <signal.h> 16 17 #if !defined(lint) 18 static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; 19 static const char rcsid[] = "@(#)$Id$"; 20 #endif 21 22 23 #define STRERROR(x) strerror(x) 24 25 extern int optind; 26 extern char *optarg; 27 28 extern ipmon_saver_t executesaver; 29 extern ipmon_saver_t filesaver; 30 extern ipmon_saver_t nothingsaver; 31 extern ipmon_saver_t snmpv1saver; 32 extern ipmon_saver_t snmpv2saver; 33 extern ipmon_saver_t syslogsaver; 34 35 36 struct flags { 37 int value; 38 char flag; 39 }; 40 41 typedef struct logsource { 42 int fd; 43 int logtype; 44 char *file; 45 int regular; 46 size_t size; 47 } logsource_t; 48 49 typedef struct config { 50 int opts; 51 int maxfd; 52 logsource_t logsrc[3]; 53 fd_set fdmr; 54 FILE *blog; 55 char *bfile; 56 FILE *log; 57 char *file; 58 char *cfile; 59 } config_t; 60 61 typedef struct icmp_subtype { 62 int ist_val; 63 char *ist_name; 64 } icmp_subtype_t; 65 66 typedef struct icmp_type { 67 int it_val; 68 struct icmp_subtype *it_subtable; 69 size_t it_stsize; 70 char *it_name; 71 } icmp_type_t; 72 73 74 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) 75 76 77 struct flags tcpfl[] = { 78 { TH_ACK, 'A' }, 79 { TH_RST, 'R' }, 80 { TH_SYN, 'S' }, 81 { TH_FIN, 'F' }, 82 { TH_URG, 'U' }, 83 { TH_PUSH,'P' }, 84 { TH_ECN, 'E' }, 85 { TH_CWR, 'C' }, 86 { 0, '\0' } 87 }; 88 89 char *reasons[] = { 90 "filter-rule", 91 "log-or-block_1", 92 "pps-rate", 93 "jumbogram", 94 "makefrip-fail", 95 "state_add-fail", 96 "updateipid-fail", 97 "log-or-block_2", 98 "decap-fail", 99 "auth_new-fail", 100 "auth_captured", 101 "coalesce-fail", 102 "pullup-fail", 103 "auth-feedback", 104 "bad-frag", 105 "natv4_out-fail", 106 "natv4_in-fail", 107 "natv6_out-fail", 108 "natv6_in-fail", 109 }; 110 111 #if SOLARIS 112 static char *pidfile = "/etc/opt/ipf/ipmon.pid"; 113 #else 114 static char *pidfile = "/var/run/ipmon.pid"; 115 #endif 116 117 static char line[2048]; 118 static int donehup = 0; 119 static void usage(char *); 120 static void handlehup(int); 121 static void flushlogs(char *, FILE *); 122 static void print_log(config_t *, logsource_t *, char *, int); 123 static void print_ipflog(config_t *, char *, int); 124 static void print_natlog(config_t *, char *, int); 125 static void print_statelog(config_t *, char *, int); 126 static int read_log(int, int *, char *, int); 127 static void write_pid(char *); 128 static char *icmpname(u_int, u_int); 129 static char *icmpname6(u_int, u_int); 130 static icmp_type_t *find_icmptype(int, icmp_type_t *, size_t); 131 static icmp_subtype_t *find_icmpsubtype(int, icmp_subtype_t *, size_t); 132 static struct tm *get_tm(time_t); 133 134 char *portlocalname(int, char *, u_int); 135 int main(int, char *[]); 136 137 static void logopts(int, char *); 138 static void init_tabs(void); 139 static char *getlocalproto(u_int); 140 static void openlogs(config_t *conf); 141 static int read_loginfo(config_t *conf); 142 static void initconfig(config_t *conf); 143 144 static char **protocols = NULL; 145 static char **udp_ports = NULL; 146 static char **tcp_ports = NULL; 147 148 149 #define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b)) 150 151 #ifndef LOGFAC 152 #define LOGFAC LOG_LOCAL0 153 #endif 154 int logfac = LOGFAC; 155 int ipmonopts = 0; 156 int opts = OPT_NORESOLVE; 157 int use_inet6 = 0; 158 159 160 static icmp_subtype_t icmpunreachnames[] = { 161 { ICMP_UNREACH_NET, "net" }, 162 { ICMP_UNREACH_HOST, "host" }, 163 { ICMP_UNREACH_PROTOCOL, "protocol" }, 164 { ICMP_UNREACH_PORT, "port" }, 165 { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 166 { ICMP_UNREACH_SRCFAIL, "srcfail" }, 167 { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 168 { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 169 { ICMP_UNREACH_NET, "isolated" }, 170 { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 171 { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 172 { ICMP_UNREACH_TOSNET, "tosnet" }, 173 { ICMP_UNREACH_TOSHOST, "toshost" }, 174 { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 175 { -2, NULL } 176 }; 177 178 static icmp_subtype_t redirectnames[] = { 179 { ICMP_REDIRECT_NET, "net" }, 180 { ICMP_REDIRECT_HOST, "host" }, 181 { ICMP_REDIRECT_TOSNET, "tosnet" }, 182 { ICMP_REDIRECT_TOSHOST, "toshost" }, 183 { -2, NULL } 184 }; 185 186 static icmp_subtype_t timxceednames[] = { 187 { ICMP_TIMXCEED_INTRANS, "transit" }, 188 { ICMP_TIMXCEED_REASS, "reassem" }, 189 { -2, NULL } 190 }; 191 192 static icmp_subtype_t paramnames[] = { 193 { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 194 { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 195 { ICMP_PARAMPROB_LENGTH, "length" }, 196 { -2, NULL } 197 }; 198 199 static icmp_type_t icmptypes4[] = { 200 { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 201 { -1, NULL, 0, NULL }, 202 { -1, NULL, 0, NULL }, 203 { ICMP_UNREACH, icmpunreachnames, 204 IST_SZ(icmpunreachnames),"unreach" }, 205 { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 206 { ICMP_REDIRECT, redirectnames, 207 IST_SZ(redirectnames), "redirect" }, 208 { -1, NULL, 0, NULL }, 209 { -1, NULL, 0, NULL }, 210 { ICMP_ECHO, NULL, 0, "echo" }, 211 { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 212 { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 213 { ICMP_TIMXCEED, timxceednames, 214 IST_SZ(timxceednames), "timxceed" }, 215 { ICMP_PARAMPROB, paramnames, 216 IST_SZ(paramnames), "paramprob" }, 217 { ICMP_TSTAMP, NULL, 0, "timestamp" }, 218 { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 219 { ICMP_IREQ, NULL, 0, "inforeq" }, 220 { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 221 { ICMP_MASKREQ, NULL, 0, "maskreq" }, 222 { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 223 { -2, NULL, 0, NULL } 224 }; 225 226 static icmp_subtype_t icmpredirect6[] = { 227 { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 228 { ICMP6_DST_UNREACH_ADMIN, "admin" }, 229 { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 230 { ICMP6_DST_UNREACH_ADDR, "address" }, 231 { ICMP6_DST_UNREACH_NOPORT, "noport" }, 232 { -2, NULL } 233 }; 234 235 static icmp_subtype_t icmptimexceed6[] = { 236 { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 237 { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 238 { -2, NULL } 239 }; 240 241 static icmp_subtype_t icmpparamprob6[] = { 242 { ICMP6_PARAMPROB_HEADER, "header" }, 243 { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 244 { ICMP6_PARAMPROB_OPTION, "option" }, 245 { -2, NULL } 246 }; 247 248 static icmp_subtype_t icmpquerysubject6[] = { 249 { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 250 { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 251 { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 252 { -2, NULL }, 253 }; 254 255 static icmp_subtype_t icmpnodeinfo6[] = { 256 { ICMP6_NI_SUCCESS, "success" }, 257 { ICMP6_NI_REFUSED, "refused" }, 258 { ICMP6_NI_UNKNOWN, "unknown" }, 259 { -2, NULL } 260 }; 261 262 static icmp_subtype_t icmprenumber6[] = { 263 { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 264 { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 265 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 266 { -2, NULL } 267 }; 268 269 static icmp_type_t icmptypes6[] = { 270 { 0, NULL, 0, NULL }, 271 { ICMP6_DST_UNREACH, icmpredirect6, 272 IST_SZ(icmpredirect6), "unreach" }, 273 { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 274 { ICMP6_TIME_EXCEEDED, icmptimexceed6, 275 IST_SZ(icmptimexceed6), "timxceed" }, 276 { ICMP6_PARAM_PROB, icmpparamprob6, 277 IST_SZ(icmpparamprob6), "paramprob" }, 278 { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 279 { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 280 { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 281 IST_SZ(icmpquerysubject6), "groupmemberquery" }, 282 { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 283 { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 284 { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 285 { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 286 { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 287 { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 288 { ND_REDIRECT, NULL, 0, "redirect" }, 289 { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 290 IST_SZ(icmprenumber6), "routerrenumber" }, 291 { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 292 { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 293 { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 294 { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 295 { ICMP6_NI_QUERY, icmpnodeinfo6, 296 IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 297 { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 298 { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 299 { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 300 { -2, NULL, 0, NULL } 301 }; 302 303 static icmp_subtype_t *find_icmpsubtype(type, table, tablesz) 304 int type; 305 icmp_subtype_t *table; 306 size_t tablesz; 307 { 308 icmp_subtype_t *ist; 309 int i; 310 311 if (tablesz < 2) 312 return NULL; 313 314 if ((type < 0) || (type > table[tablesz - 2].ist_val)) 315 return NULL; 316 317 i = type; 318 if (table[type].ist_val == type) 319 return table + type; 320 321 for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) 322 if (ist->ist_val == type) 323 return ist; 324 return NULL; 325 } 326 327 328 static icmp_type_t *find_icmptype(type, table, tablesz) 329 int type; 330 icmp_type_t *table; 331 size_t tablesz; 332 { 333 icmp_type_t *it; 334 int i; 335 336 if (tablesz < 2) 337 return NULL; 338 339 if ((type < 0) || (type > table[tablesz - 2].it_val)) 340 return NULL; 341 342 i = type; 343 if (table[type].it_val == type) 344 return table + type; 345 346 for (i = 0, it = table; it->it_val != -2; i++, it++) 347 if (it->it_val == type) 348 return it; 349 return NULL; 350 } 351 352 353 static void handlehup(sig) 354 int sig; 355 { 356 signal(SIGHUP, handlehup); 357 donehup = 1; 358 } 359 360 361 static void init_tabs() 362 { 363 struct protoent *p; 364 struct servent *s; 365 char *name, **tab; 366 int port, i; 367 368 if (protocols != NULL) { 369 for (i = 0; i < 256; i++) 370 if (protocols[i] != NULL) { 371 free(protocols[i]); 372 protocols[i] = NULL; 373 } 374 free(protocols); 375 protocols = NULL; 376 } 377 protocols = (char **)malloc(256 * sizeof(*protocols)); 378 if (protocols != NULL) { 379 bzero((char *)protocols, 256 * sizeof(*protocols)); 380 381 setprotoent(1); 382 while ((p = getprotoent()) != NULL) 383 if (p->p_proto >= 0 && p->p_proto <= 255 && 384 p->p_name != NULL && protocols[p->p_proto] == NULL) 385 protocols[p->p_proto] = strdup(p->p_name); 386 endprotoent(); 387 if (protocols[0]) 388 free(protocols[0]); 389 protocols[0] = strdup("ip"); 390 } 391 392 if (udp_ports != NULL) { 393 for (i = 0; i < 65536; i++) 394 if (udp_ports[i] != NULL) { 395 free(udp_ports[i]); 396 udp_ports[i] = NULL; 397 } 398 free(udp_ports); 399 udp_ports = NULL; 400 } 401 udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 402 if (udp_ports != NULL) 403 bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 404 405 if (tcp_ports != NULL) { 406 for (i = 0; i < 65536; i++) 407 if (tcp_ports[i] != NULL) { 408 free(tcp_ports[i]); 409 tcp_ports[i] = NULL; 410 } 411 free(tcp_ports); 412 tcp_ports = NULL; 413 } 414 tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 415 if (tcp_ports != NULL) 416 bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 417 418 setservent(1); 419 while ((s = getservent()) != NULL) { 420 if (s->s_proto == NULL) 421 continue; 422 else if (!strcmp(s->s_proto, "tcp")) { 423 port = ntohs(s->s_port); 424 name = s->s_name; 425 tab = tcp_ports; 426 } else if (!strcmp(s->s_proto, "udp")) { 427 port = ntohs(s->s_port); 428 name = s->s_name; 429 tab = udp_ports; 430 } else 431 continue; 432 if ((port < 0 || port > 65535) || (name == NULL)) 433 continue; 434 if (tab != NULL) 435 tab[port] = strdup(name); 436 } 437 endservent(); 438 } 439 440 441 static char *getlocalproto(p) 442 u_int p; 443 { 444 static char pnum[4]; 445 char *s; 446 447 p &= 0xff; 448 s = protocols ? protocols[p] : NULL; 449 if (s == NULL) { 450 sprintf(pnum, "%u", p); 451 s = pnum; 452 } 453 return s; 454 } 455 456 457 static int read_log(fd, lenp, buf, bufsize) 458 int fd, bufsize, *lenp; 459 char *buf; 460 { 461 int nr; 462 463 if (bufsize > IPFILTER_LOGSIZE) 464 bufsize = IPFILTER_LOGSIZE; 465 466 nr = read(fd, buf, bufsize); 467 if (!nr) 468 return 2; 469 if ((nr < 0) && (errno != EINTR)) 470 return -1; 471 *lenp = nr; 472 return 0; 473 } 474 475 476 char *portlocalname(res, proto, port) 477 int res; 478 char *proto; 479 u_int port; 480 { 481 static char pname[8]; 482 char *s; 483 484 port = ntohs(port); 485 port &= 0xffff; 486 sprintf(pname, "%u", port); 487 if (!res || (ipmonopts & IPMON_PORTNUM)) 488 return pname; 489 s = NULL; 490 if (!strcmp(proto, "tcp")) 491 s = tcp_ports[port]; 492 else if (!strcmp(proto, "udp")) 493 s = udp_ports[port]; 494 if (s == NULL) 495 s = pname; 496 return s; 497 } 498 499 500 static char *icmpname(type, code) 501 u_int type; 502 u_int code; 503 { 504 static char name[80]; 505 icmp_subtype_t *ist; 506 icmp_type_t *it; 507 char *s; 508 509 s = NULL; 510 it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); 511 if (it != NULL) 512 s = it->it_name; 513 514 if (s == NULL) 515 sprintf(name, "icmptype(%d)/", type); 516 else 517 sprintf(name, "%s/", s); 518 519 ist = NULL; 520 if (it != NULL && it->it_subtable != NULL) 521 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 522 523 if (ist != NULL && ist->ist_name != NULL) 524 strcat(name, ist->ist_name); 525 else 526 sprintf(name + strlen(name), "%d", code); 527 528 return name; 529 } 530 531 static char *icmpname6(type, code) 532 u_int type; 533 u_int code; 534 { 535 static char name[80]; 536 icmp_subtype_t *ist; 537 icmp_type_t *it; 538 char *s; 539 540 s = NULL; 541 it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 542 if (it != NULL) 543 s = it->it_name; 544 545 if (s == NULL) 546 sprintf(name, "icmpv6type(%d)/", type); 547 else 548 sprintf(name, "%s/", s); 549 550 ist = NULL; 551 if (it != NULL && it->it_subtable != NULL) 552 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 553 554 if (ist != NULL && ist->ist_name != NULL) 555 strcat(name, ist->ist_name); 556 else 557 sprintf(name + strlen(name), "%d", code); 558 559 return name; 560 } 561 562 563 void dumphex(log, dopts, buf, len) 564 FILE *log; 565 int dopts; 566 char *buf; 567 int len; 568 { 569 char hline[80]; 570 int i, j, k; 571 u_char *s = (u_char *)buf, *t = (u_char *)hline; 572 573 if (buf == NULL || len == 0) 574 return; 575 576 *hline = '\0'; 577 578 for (i = len, j = 0; i; i--, j++, s++) { 579 if (j && !(j & 0xf)) { 580 *t++ = '\n'; 581 *t = '\0'; 582 if ((dopts & IPMON_SYSLOG)) 583 syslog(LOG_INFO, "%s", hline); 584 else if (log != NULL) 585 fputs(hline, log); 586 t = (u_char *)hline; 587 *t = '\0'; 588 } 589 sprintf((char *)t, "%02x", *s & 0xff); 590 t += 2; 591 if (!((j + 1) & 0xf)) { 592 s -= 15; 593 sprintf((char *)t, " "); 594 t += 8; 595 for (k = 16; k; k--, s++) 596 *t++ = (isprint(*s) ? *s : '.'); 597 s--; 598 } 599 600 if ((j + 1) & 0xf) 601 *t++ = ' ';; 602 } 603 604 if (j & 0xf) { 605 for (k = 16 - (j & 0xf); k; k--) { 606 *t++ = ' '; 607 *t++ = ' '; 608 *t++ = ' '; 609 } 610 sprintf((char *)t, " "); 611 t += 7; 612 s -= j & 0xf; 613 for (k = j & 0xf; k; k--, s++) 614 *t++ = (isprint(*s) ? *s : '.'); 615 *t++ = '\n'; 616 *t = '\0'; 617 } 618 if ((dopts & IPMON_SYSLOG) != 0) 619 syslog(LOG_INFO, "%s", hline); 620 else if (log != NULL) { 621 fputs(hline, log); 622 fflush(log); 623 } 624 } 625 626 627 static struct tm *get_tm(sec) 628 time_t sec; 629 { 630 struct tm *tm; 631 time_t t; 632 633 t = sec; 634 tm = localtime(&t); 635 return tm; 636 } 637 638 static void print_natlog(conf, buf, blen) 639 config_t *conf; 640 char *buf; 641 int blen; 642 { 643 static u_32_t seqnum = 0; 644 int res, i, len, family; 645 struct natlog *nl; 646 struct tm *tm; 647 iplog_t *ipl; 648 char *proto; 649 int simple; 650 char *t; 651 652 t = line; 653 simple = 0; 654 ipl = (iplog_t *)buf; 655 if (ipl->ipl_seqnum != seqnum) { 656 if ((ipmonopts & IPMON_SYSLOG) != 0) { 657 syslog(LOG_WARNING, 658 "missed %u NAT log entries: %u %u", 659 ipl->ipl_seqnum - seqnum, seqnum, 660 ipl->ipl_seqnum); 661 } else { 662 (void) fprintf(conf->log, 663 "missed %u NAT log entries: %u %u\n", 664 ipl->ipl_seqnum - seqnum, seqnum, 665 ipl->ipl_seqnum); 666 } 667 } 668 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 669 670 nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 671 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 672 tm = get_tm(ipl->ipl_sec); 673 len = sizeof(line); 674 675 if (!(ipmonopts & IPMON_SYSLOG)) { 676 (void) strftime(t, len, "%d/%m/%Y ", tm); 677 i = strlen(t); 678 len -= i; 679 t += i; 680 } 681 (void) strftime(t, len, "%T", tm); 682 t += strlen(t); 683 sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); 684 t += strlen(t); 685 686 switch (nl->nl_action) 687 { 688 case NL_NEW : 689 strcpy(t, "NAT:NEW"); 690 break; 691 692 case NL_FLUSH : 693 strcpy(t, "NAT:FLUSH"); 694 break; 695 696 case NL_CLONE : 697 strcpy(t, "NAT:CLONE"); 698 break; 699 700 case NL_EXPIRE : 701 strcpy(t, "NAT:EXPIRE"); 702 break; 703 704 case NL_DESTROY : 705 strcpy(t, "NAT:DESTROY"); 706 break; 707 708 case NL_PURGE : 709 strcpy(t, "NAT:PURGE"); 710 break; 711 712 default : 713 sprintf(t, "NAT:Action(%d)", nl->nl_action); 714 break; 715 } 716 t += strlen(t); 717 718 719 switch (nl->nl_type) 720 { 721 case NAT_MAP : 722 strcpy(t, "-MAP "); 723 simple = 1; 724 break; 725 726 case NAT_REDIRECT : 727 strcpy(t, "-RDR "); 728 simple = 1; 729 break; 730 731 case NAT_BIMAP : 732 strcpy(t, "-BIMAP "); 733 simple = 1; 734 break; 735 736 case NAT_MAPBLK : 737 strcpy(t, "-MAPBLOCK "); 738 simple = 1; 739 break; 740 741 case NAT_REWRITE|NAT_MAP : 742 strcpy(t, "-RWR_MAP "); 743 break; 744 745 case NAT_REWRITE|NAT_REDIRECT : 746 strcpy(t, "-RWR_RDR "); 747 break; 748 749 case NAT_ENCAP|NAT_MAP : 750 strcpy(t, "-ENC_MAP "); 751 break; 752 753 case NAT_ENCAP|NAT_REDIRECT : 754 strcpy(t, "-ENC_RDR "); 755 break; 756 757 case NAT_DIVERTUDP|NAT_MAP : 758 strcpy(t, "-DIV_MAP "); 759 break; 760 761 case NAT_DIVERTUDP|NAT_REDIRECT : 762 strcpy(t, "-DIV_RDR "); 763 break; 764 765 default : 766 sprintf(t, "-Type(%d) ", nl->nl_type); 767 break; 768 } 769 t += strlen(t); 770 771 proto = getlocalproto(nl->nl_p[0]); 772 773 family = vtof(nl->nl_v[0]); 774 775 if (simple == 1) { 776 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), 777 portlocalname(res, proto, (u_int)nl->nl_osrcport)); 778 t += strlen(t); 779 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 780 portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 781 t += strlen(t); 782 sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), 783 portlocalname(res, proto, (u_int)nl->nl_odstport)); 784 } else { 785 sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), 786 portlocalname(res, proto, (u_int)nl->nl_osrcport)); 787 t += strlen(t); 788 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), 789 portlocalname(res, proto, (u_int)nl->nl_odstport)); 790 t += strlen(t); 791 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 792 portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 793 t += strlen(t); 794 sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), 795 portlocalname(res, proto, (u_int)nl->nl_ndstport)); 796 } 797 t += strlen(t); 798 799 strcpy(t, getlocalproto(nl->nl_p[0])); 800 t += strlen(t); 801 802 if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { 803 #ifdef USE_QUAD_T 804 # ifdef PRId64 805 sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" 806 PRId64, 807 # else 808 sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 809 # endif 810 #else 811 sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 812 #endif 813 nl->nl_pkts[0], nl->nl_pkts[1], 814 nl->nl_bytes[0], nl->nl_bytes[1]); 815 t += strlen(t); 816 } 817 818 *t++ = '\n'; 819 *t++ = '\0'; 820 if (ipmonopts & IPMON_SYSLOG) 821 syslog(LOG_INFO, "%s", line); 822 else if (conf->log != NULL) 823 (void) fprintf(conf->log, "%s", line); 824 } 825 826 827 static void print_statelog(conf, buf, blen) 828 config_t *conf; 829 char *buf; 830 int blen; 831 { 832 static u_32_t seqnum = 0; 833 int res, i, len, family; 834 struct ipslog *sl; 835 char *t, *proto; 836 struct tm *tm; 837 iplog_t *ipl; 838 839 t = line; 840 ipl = (iplog_t *)buf; 841 if (ipl->ipl_seqnum != seqnum) { 842 if ((ipmonopts & IPMON_SYSLOG) != 0) { 843 syslog(LOG_WARNING, 844 "missed %u state log entries: %u %u", 845 ipl->ipl_seqnum - seqnum, seqnum, 846 ipl->ipl_seqnum); 847 } else { 848 (void) fprintf(conf->log, 849 "missed %u state log entries: %u %u\n", 850 ipl->ipl_seqnum - seqnum, seqnum, 851 ipl->ipl_seqnum); 852 } 853 } 854 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 855 856 sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 857 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 858 tm = get_tm(ipl->ipl_sec); 859 len = sizeof(line); 860 if (!(ipmonopts & IPMON_SYSLOG)) { 861 (void) strftime(t, len, "%d/%m/%Y ", tm); 862 i = strlen(t); 863 len -= i; 864 t += i; 865 } 866 (void) strftime(t, len, "%T", tm); 867 t += strlen(t); 868 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 869 t += strlen(t); 870 871 family = vtof(sl->isl_v); 872 873 switch (sl->isl_type) 874 { 875 case ISL_NEW : 876 strcpy(t, "STATE:NEW "); 877 break; 878 879 case ISL_CLONE : 880 strcpy(t, "STATE:CLONED "); 881 break; 882 883 case ISL_EXPIRE : 884 if ((sl->isl_p == IPPROTO_TCP) && 885 (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 886 sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 887 strcpy(t, "STATE:CLOSE "); 888 else 889 strcpy(t, "STATE:EXPIRE "); 890 break; 891 892 case ISL_FLUSH : 893 strcpy(t, "STATE:FLUSH "); 894 break; 895 896 case ISL_INTERMEDIATE : 897 strcpy(t, "STATE:INTERMEDIATE "); 898 break; 899 900 case ISL_REMOVE : 901 strcpy(t, "STATE:REMOVE "); 902 break; 903 904 case ISL_KILLED : 905 strcpy(t, "STATE:KILLED "); 906 break; 907 908 case ISL_UNLOAD : 909 strcpy(t, "STATE:UNLOAD "); 910 break; 911 912 default : 913 sprintf(t, "Type: %d ", sl->isl_type); 914 break; 915 } 916 t += strlen(t); 917 918 proto = getlocalproto(sl->isl_p); 919 920 if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 921 sprintf(t, "%s,%s -> ", 922 hostname(family, (u_32_t *)&sl->isl_src), 923 portlocalname(res, proto, (u_int)sl->isl_sport)); 924 t += strlen(t); 925 sprintf(t, "%s,%s PR %s", 926 hostname(family, (u_32_t *)&sl->isl_dst), 927 portlocalname(res, proto, (u_int)sl->isl_dport), proto); 928 } else if (sl->isl_p == IPPROTO_ICMP) { 929 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 930 t += strlen(t); 931 sprintf(t, "%s PR icmp %d", 932 hostname(family, (u_32_t *)&sl->isl_dst), 933 sl->isl_itype); 934 } else if (sl->isl_p == IPPROTO_ICMPV6) { 935 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 936 t += strlen(t); 937 sprintf(t, "%s PR icmpv6 %d", 938 hostname(family, (u_32_t *)&sl->isl_dst), 939 sl->isl_itype); 940 } else { 941 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 942 t += strlen(t); 943 sprintf(t, "%s PR %s", 944 hostname(family, (u_32_t *)&sl->isl_dst), proto); 945 } 946 t += strlen(t); 947 if (sl->isl_tag != FR_NOLOGTAG) { 948 sprintf(t, " tag %u", sl->isl_tag); 949 t += strlen(t); 950 } 951 if (sl->isl_type != ISL_NEW) { 952 sprintf(t, 953 #ifdef USE_QUAD_T 954 #ifdef PRId64 955 " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 956 " Pkts out %" PRId64 " Bytes out %" PRId64 957 " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 958 " Pkts out %" PRId64 " Bytes out %" PRId64, 959 #else 960 " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd", 961 #endif /* PRId64 */ 962 #else 963 " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld", 964 #endif 965 sl->isl_pkts[0], sl->isl_bytes[0], 966 sl->isl_pkts[1], sl->isl_bytes[1], 967 sl->isl_pkts[2], sl->isl_bytes[2], 968 sl->isl_pkts[3], sl->isl_bytes[3]); 969 970 t += strlen(t); 971 } 972 973 *t++ = '\n'; 974 *t++ = '\0'; 975 if (ipmonopts & IPMON_SYSLOG) 976 syslog(LOG_INFO, "%s", line); 977 else if (conf->log != NULL) 978 (void) fprintf(conf->log, "%s", line); 979 } 980 981 982 static void print_log(conf, log, buf, blen) 983 config_t *conf; 984 logsource_t *log; 985 char *buf; 986 int blen; 987 { 988 char *bp, *bpo; 989 iplog_t *ipl; 990 int psize; 991 992 bp = NULL; 993 bpo = NULL; 994 995 while (blen > 0) { 996 ipl = (iplog_t *)buf; 997 if ((u_long)ipl & (sizeof(long)-1)) { 998 if (bp) 999 bpo = bp; 1000 bp = (char *)malloc(blen); 1001 bcopy((char *)ipl, bp, blen); 1002 if (bpo) { 1003 free(bpo); 1004 bpo = NULL; 1005 } 1006 buf = bp; 1007 continue; 1008 } 1009 1010 psize = ipl->ipl_dsize; 1011 if (psize > blen) 1012 break; 1013 1014 if (conf->blog != NULL) { 1015 fwrite(buf, psize, 1, conf->blog); 1016 fflush(conf->blog); 1017 } 1018 1019 if (log->logtype == IPL_LOGIPF) { 1020 if (ipl->ipl_magic == IPL_MAGIC) 1021 print_ipflog(conf, buf, psize); 1022 1023 } else if (log->logtype == IPL_LOGNAT) { 1024 if (ipl->ipl_magic == IPL_MAGIC_NAT) 1025 print_natlog(conf, buf, psize); 1026 1027 } else if (log->logtype == IPL_LOGSTATE) { 1028 if (ipl->ipl_magic == IPL_MAGIC_STATE) 1029 print_statelog(conf, buf, psize); 1030 } 1031 1032 blen -= psize; 1033 buf += psize; 1034 } 1035 if (bp) 1036 free(bp); 1037 return; 1038 } 1039 1040 1041 static void print_ipflog(conf, buf, blen) 1042 config_t *conf; 1043 char *buf; 1044 int blen; 1045 { 1046 static u_32_t seqnum = 0; 1047 int i, f, lvl, res, len, off, plen, ipoff, defaction; 1048 struct icmp *icmp; 1049 struct icmp *ic; 1050 char *t, *proto; 1051 ip_t *ipc, *ip; 1052 struct tm *tm; 1053 u_32_t *s, *d; 1054 u_short hl, p; 1055 ipflog_t *ipf; 1056 iplog_t *ipl; 1057 tcphdr_t *tp; 1058 #ifdef USE_INET6 1059 struct ip6_ext *ehp; 1060 u_short ehl; 1061 ip6_t *ip6; 1062 int go; 1063 #endif 1064 1065 ipl = (iplog_t *)buf; 1066 if (ipl->ipl_seqnum != seqnum) { 1067 if ((ipmonopts & IPMON_SYSLOG) != 0) { 1068 syslog(LOG_WARNING, 1069 "missed %u ipf log entries: %u %u", 1070 ipl->ipl_seqnum - seqnum, seqnum, 1071 ipl->ipl_seqnum); 1072 } else { 1073 (void) fprintf(conf->log, 1074 "missed %u ipf log entries: %u %u\n", 1075 ipl->ipl_seqnum - seqnum, seqnum, 1076 ipl->ipl_seqnum); 1077 } 1078 } 1079 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 1080 1081 ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 1082 ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 1083 f = ipf->fl_family; 1084 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 1085 t = line; 1086 *t = '\0'; 1087 tm = get_tm(ipl->ipl_sec); 1088 1089 len = sizeof(line); 1090 if (!(ipmonopts & IPMON_SYSLOG)) { 1091 (void) strftime(t, len, "%d/%m/%Y ", tm); 1092 i = strlen(t); 1093 len -= i; 1094 t += i; 1095 } 1096 (void) strftime(t, len, "%T", tm); 1097 t += strlen(t); 1098 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 1099 t += strlen(t); 1100 if (ipl->ipl_count > 1) { 1101 sprintf(t, "%dx ", ipl->ipl_count); 1102 t += strlen(t); 1103 } 1104 { 1105 char ifname[sizeof(ipf->fl_ifname) + 1]; 1106 1107 strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1108 ifname[sizeof(ipf->fl_ifname)] = '\0'; 1109 sprintf(t, "%s", ifname); 1110 t += strlen(t); 1111 # if SOLARIS 1112 if (ISALPHA(*(t - 1))) { 1113 sprintf(t, "%d", ipf->fl_unit); 1114 t += strlen(t); 1115 } 1116 # endif 1117 } 1118 if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) 1119 strcat(t, " @-1:"); 1120 else if (ipf->fl_group[0] == '\0') 1121 (void) strcpy(t, " @0:"); 1122 else 1123 sprintf(t, " @%s:", ipf->fl_group); 1124 t += strlen(t); 1125 if (ipf->fl_rule == 0xffffffff) 1126 strcat(t, "-1 "); 1127 else 1128 sprintf(t, "%u ", ipf->fl_rule + 1); 1129 t += strlen(t); 1130 1131 lvl = LOG_NOTICE; 1132 1133 if (ipf->fl_lflags & FI_SHORT) { 1134 *t++ = 'S'; 1135 lvl = LOG_ERR; 1136 } 1137 1138 if (FR_ISPASS(ipf->fl_flags)) { 1139 if (ipf->fl_flags & FR_LOGP) 1140 *t++ = 'p'; 1141 else 1142 *t++ = 'P'; 1143 } else if (FR_ISBLOCK(ipf->fl_flags)) { 1144 if (ipf->fl_flags & FR_LOGB) 1145 *t++ = 'b'; 1146 else 1147 *t++ = 'B'; 1148 lvl = LOG_WARNING; 1149 } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 1150 *t++ = 'L'; 1151 lvl = LOG_INFO; 1152 } else if (ipf->fl_flags & FF_LOGNOMATCH) { 1153 *t++ = 'n'; 1154 } else { 1155 *t++ = '?'; 1156 lvl = LOG_EMERG; 1157 } 1158 if (ipf->fl_loglevel != 0xffff) 1159 lvl = ipf->fl_loglevel; 1160 *t++ = ' '; 1161 *t = '\0'; 1162 1163 if (f == AF_INET) { 1164 hl = IP_HL(ip) << 2; 1165 ipoff = ntohs(ip->ip_off); 1166 off = ipoff & IP_OFFMASK; 1167 p = (u_short)ip->ip_p; 1168 s = (u_32_t *)&ip->ip_src; 1169 d = (u_32_t *)&ip->ip_dst; 1170 plen = ntohs(ip->ip_len); 1171 } else 1172 #ifdef USE_INET6 1173 if (f == AF_INET6) { 1174 off = 0; 1175 ipoff = 0; 1176 hl = sizeof(ip6_t); 1177 ip6 = (ip6_t *)ip; 1178 p = (u_short)ip6->ip6_nxt; 1179 s = (u_32_t *)&ip6->ip6_src; 1180 d = (u_32_t *)&ip6->ip6_dst; 1181 plen = hl + ntohs(ip6->ip6_plen); 1182 go = 1; 1183 ehp = (struct ip6_ext *)((char *)ip6 + hl); 1184 while (go == 1) { 1185 switch (p) 1186 { 1187 case IPPROTO_HOPOPTS : 1188 case IPPROTO_MOBILITY : 1189 case IPPROTO_DSTOPTS : 1190 case IPPROTO_ROUTING : 1191 case IPPROTO_AH : 1192 p = ehp->ip6e_nxt; 1193 ehl = 8 + (ehp->ip6e_len << 3); 1194 hl += ehl; 1195 ehp = (struct ip6_ext *)((char *)ehp + ehl); 1196 break; 1197 case IPPROTO_FRAGMENT : 1198 hl += sizeof(struct ip6_frag); 1199 /* FALLTHROUGH */ 1200 default : 1201 go = 0; 1202 break; 1203 } 1204 } 1205 } else 1206 #endif 1207 { 1208 goto printipflog; 1209 } 1210 proto = getlocalproto(p); 1211 1212 if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 1213 tp = (tcphdr_t *)((char *)ip + hl); 1214 if (!(ipf->fl_lflags & FI_SHORT)) { 1215 sprintf(t, "%s,%s -> ", hostname(f, s), 1216 portlocalname(res, proto, (u_int)tp->th_sport)); 1217 t += strlen(t); 1218 sprintf(t, "%s,%s PR %s len %hu %hu", 1219 hostname(f, d), 1220 portlocalname(res, proto, (u_int)tp->th_dport), 1221 proto, hl, plen); 1222 t += strlen(t); 1223 1224 if (p == IPPROTO_TCP) { 1225 *t++ = ' '; 1226 *t++ = '-'; 1227 for (i = 0; tcpfl[i].value; i++) 1228 if (tp->th_flags & tcpfl[i].value) 1229 *t++ = tcpfl[i].flag; 1230 if (ipmonopts & IPMON_VERBOSE) { 1231 sprintf(t, " %lu %lu %hu", 1232 (u_long)(ntohl(tp->th_seq)), 1233 (u_long)(ntohl(tp->th_ack)), 1234 ntohs(tp->th_win)); 1235 t += strlen(t); 1236 } 1237 } 1238 *t = '\0'; 1239 } else { 1240 sprintf(t, "%s -> ", hostname(f, s)); 1241 t += strlen(t); 1242 sprintf(t, "%s PR %s len %hu %hu", 1243 hostname(f, d), proto, hl, plen); 1244 } 1245 #if defined(AF_INET6) && defined(IPPROTO_ICMPV6) 1246 } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { 1247 ic = (struct icmp *)((char *)ip + hl); 1248 sprintf(t, "%s -> ", hostname(f, s)); 1249 t += strlen(t); 1250 sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 1251 hostname(f, d), hl, plen, 1252 icmpname6(ic->icmp_type, ic->icmp_code)); 1253 #endif 1254 } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { 1255 ic = (struct icmp *)((char *)ip + hl); 1256 sprintf(t, "%s -> ", hostname(f, s)); 1257 t += strlen(t); 1258 sprintf(t, "%s PR icmp len %hu %hu icmp %s", 1259 hostname(f, d), hl, plen, 1260 icmpname(ic->icmp_type, ic->icmp_code)); 1261 if (ic->icmp_type == ICMP_UNREACH || 1262 ic->icmp_type == ICMP_SOURCEQUENCH || 1263 ic->icmp_type == ICMP_PARAMPROB || 1264 ic->icmp_type == ICMP_REDIRECT || 1265 ic->icmp_type == ICMP_TIMXCEED) { 1266 ipc = &ic->icmp_ip; 1267 i = ntohs(ipc->ip_len); 1268 /* 1269 * XXX - try to guess endian of ip_len in ICMP 1270 * returned data. 1271 */ 1272 if (i > 1500) 1273 i = ipc->ip_len; 1274 ipoff = ntohs(ipc->ip_off); 1275 proto = getlocalproto(ipc->ip_p); 1276 1277 if (!(ipoff & IP_OFFMASK) && 1278 ((ipc->ip_p == IPPROTO_TCP) || 1279 (ipc->ip_p == IPPROTO_UDP))) { 1280 tp = (tcphdr_t *)((char *)ipc + hl); 1281 t += strlen(t); 1282 sprintf(t, " for %s,%s -", 1283 HOSTNAMEV4(ipc->ip_src), 1284 portlocalname(res, proto, 1285 (u_int)tp->th_sport)); 1286 t += strlen(t); 1287 sprintf(t, " %s,%s PR %s len %hu %hu", 1288 HOSTNAMEV4(ipc->ip_dst), 1289 portlocalname(res, proto, 1290 (u_int)tp->th_dport), 1291 proto, IP_HL(ipc) << 2, i); 1292 } else if (!(ipoff & IP_OFFMASK) && 1293 (ipc->ip_p == IPPROTO_ICMP)) { 1294 icmp = (icmphdr_t *)((char *)ipc + hl); 1295 1296 t += strlen(t); 1297 sprintf(t, " for %s -", 1298 HOSTNAMEV4(ipc->ip_src)); 1299 t += strlen(t); 1300 sprintf(t, 1301 " %s PR icmp len %hu %hu icmp %d/%d", 1302 HOSTNAMEV4(ipc->ip_dst), 1303 IP_HL(ipc) << 2, i, 1304 icmp->icmp_type, icmp->icmp_code); 1305 } else { 1306 t += strlen(t); 1307 sprintf(t, " for %s -", 1308 HOSTNAMEV4(ipc->ip_src)); 1309 t += strlen(t); 1310 sprintf(t, " %s PR %s len %hu (%hu)", 1311 HOSTNAMEV4(ipc->ip_dst), proto, 1312 IP_HL(ipc) << 2, i); 1313 t += strlen(t); 1314 if (ipoff & IP_OFFMASK) { 1315 sprintf(t, "(frag %d:%hu@%hu%s%s)", 1316 ntohs(ipc->ip_id), 1317 i - (IP_HL(ipc) << 2), 1318 (ipoff & IP_OFFMASK) << 3, 1319 ipoff & IP_MF ? "+" : "", 1320 ipoff & IP_DF ? "-" : ""); 1321 } 1322 } 1323 1324 } 1325 } else { 1326 sprintf(t, "%s -> ", hostname(f, s)); 1327 t += strlen(t); 1328 sprintf(t, "%s PR %s len %hu (%hu)", 1329 hostname(f, d), proto, hl, plen); 1330 t += strlen(t); 1331 if (off & IP_OFFMASK) 1332 sprintf(t, " (frag %d:%hu@%hu%s%s)", 1333 ntohs(ip->ip_id), 1334 plen - hl, (off & IP_OFFMASK) << 3, 1335 ipoff & IP_MF ? "+" : "", 1336 ipoff & IP_DF ? "-" : ""); 1337 } 1338 t += strlen(t); 1339 1340 printipflog: 1341 if (ipf->fl_flags & FR_KEEPSTATE) { 1342 (void) strcpy(t, " K-S"); 1343 t += strlen(t); 1344 } 1345 1346 if (ipf->fl_flags & FR_KEEPFRAG) { 1347 (void) strcpy(t, " K-F"); 1348 t += strlen(t); 1349 } 1350 1351 if (ipf->fl_dir == 0) 1352 strcpy(t, " IN"); 1353 else if (ipf->fl_dir == 1) 1354 strcpy(t, " OUT"); 1355 t += strlen(t); 1356 if (ipf->fl_logtag != 0) { 1357 sprintf(t, " log-tag %d", ipf->fl_logtag); 1358 t += strlen(t); 1359 } 1360 if (ipf->fl_nattag.ipt_num[0] != 0) { 1361 strcpy(t, " nat-tag "); 1362 t += strlen(t); 1363 strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 1364 t += strlen(t); 1365 } 1366 if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 1367 strcpy(t, " low-ttl"); 1368 t += 8; 1369 } 1370 if ((ipf->fl_lflags & FI_OOW) != 0) { 1371 strcpy(t, " OOW"); 1372 t += 4; 1373 } 1374 if ((ipf->fl_lflags & FI_BAD) != 0) { 1375 strcpy(t, " bad"); 1376 t += 4; 1377 } 1378 if ((ipf->fl_lflags & FI_NATED) != 0) { 1379 strcpy(t, " NAT"); 1380 t += 4; 1381 } 1382 if ((ipf->fl_lflags & FI_BADNAT) != 0) { 1383 strcpy(t, " bad-NAT"); 1384 t += 8; 1385 } 1386 if ((ipf->fl_lflags & FI_BADSRC) != 0) { 1387 strcpy(t, " bad-src"); 1388 t += 8; 1389 } 1390 if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 1391 strcpy(t, " multicast"); 1392 t += 10; 1393 } 1394 if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 1395 strcpy(t, " broadcast"); 1396 t += 10; 1397 } 1398 if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 1399 FI_MBCAST) { 1400 strcpy(t, " mbcast"); 1401 t += 7; 1402 } 1403 if (ipf->fl_breason != 0) { 1404 strcpy(t, " reason:"); 1405 t += 8; 1406 strcpy(t, reasons[ipf->fl_breason]); 1407 t += strlen(reasons[ipf->fl_breason]); 1408 } 1409 *t++ = '\n'; 1410 *t++ = '\0'; 1411 defaction = 0; 1412 if (conf->cfile != NULL) 1413 defaction = check_action(buf, line, ipmonopts, lvl); 1414 1415 if (defaction == 0) { 1416 if (ipmonopts & IPMON_SYSLOG) { 1417 syslog(lvl, "%s", line); 1418 } else if (conf->log != NULL) { 1419 (void) fprintf(conf->log, "%s", line); 1420 } 1421 1422 if (ipmonopts & IPMON_HEXHDR) { 1423 dumphex(conf->log, ipmonopts, buf, 1424 sizeof(iplog_t) + sizeof(*ipf)); 1425 } 1426 if (ipmonopts & IPMON_HEXBODY) { 1427 dumphex(conf->log, ipmonopts, (char *)ip, 1428 ipf->fl_plen + ipf->fl_hlen); 1429 } else if ((ipmonopts & IPMON_LOGBODY) && 1430 (ipf->fl_flags & FR_LOGBODY)) { 1431 dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, 1432 ipf->fl_plen); 1433 } 1434 } 1435 } 1436 1437 1438 static void usage(prog) 1439 char *prog; 1440 { 1441 fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n" 1442 "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n" 1443 "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n" 1444 "\t[ <filename> ]\n", prog); 1445 exit(1); 1446 } 1447 1448 1449 static void write_pid(file) 1450 char *file; 1451 { 1452 FILE *fp = NULL; 1453 int fd; 1454 1455 if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1456 fp = fdopen(fd, "w"); 1457 if (fp == NULL) { 1458 close(fd); 1459 fprintf(stderr, 1460 "unable to open/create pid file: %s\n", file); 1461 return; 1462 } 1463 fprintf(fp, "%d", getpid()); 1464 fclose(fp); 1465 } 1466 } 1467 1468 1469 static void flushlogs(file, log) 1470 char *file; 1471 FILE *log; 1472 { 1473 int fd, flushed = 0; 1474 1475 if ((fd = open(file, O_RDWR)) == -1) { 1476 (void) fprintf(stderr, "%s: open: %s\n", 1477 file, STRERROR(errno)); 1478 exit(1); 1479 } 1480 1481 if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1482 printf("%d bytes flushed from log buffer\n", 1483 flushed); 1484 fflush(stdout); 1485 } else 1486 ipferror(fd, "SIOCIPFFB"); 1487 (void) close(fd); 1488 1489 if (flushed) { 1490 if (ipmonopts & IPMON_SYSLOG) { 1491 syslog(LOG_INFO, "%d bytes flushed from log\n", 1492 flushed); 1493 } else if ((log != stdout) && (log != NULL)) { 1494 fprintf(log, "%d bytes flushed from log\n", flushed); 1495 } 1496 } 1497 } 1498 1499 1500 static void logopts(turnon, options) 1501 int turnon; 1502 char *options; 1503 { 1504 int flags = 0; 1505 char *s; 1506 1507 for (s = options; *s; s++) 1508 { 1509 switch (*s) 1510 { 1511 case 'N' : 1512 flags |= IPMON_NAT; 1513 break; 1514 case 'S' : 1515 flags |= IPMON_STATE; 1516 break; 1517 case 'I' : 1518 flags |= IPMON_FILTER; 1519 break; 1520 default : 1521 fprintf(stderr, "Unknown log option %c\n", *s); 1522 exit(1); 1523 } 1524 } 1525 1526 if (turnon) 1527 ipmonopts |= flags; 1528 else 1529 ipmonopts &= ~(flags); 1530 } 1531 1532 static void initconfig(config_t *conf) 1533 { 1534 int i; 1535 1536 memset(conf, 0, sizeof(*conf)); 1537 1538 conf->log = stdout; 1539 conf->maxfd = -1; 1540 1541 for (i = 0; i < 3; i++) { 1542 conf->logsrc[i].fd = -1; 1543 conf->logsrc[i].logtype = -1; 1544 conf->logsrc[i].regular = -1; 1545 } 1546 1547 conf->logsrc[0].file = IPL_NAME; 1548 conf->logsrc[1].file = IPNAT_NAME; 1549 conf->logsrc[2].file = IPSTATE_NAME; 1550 1551 add_doing(&executesaver); 1552 add_doing(&snmpv1saver); 1553 add_doing(&snmpv2saver); 1554 add_doing(&syslogsaver); 1555 add_doing(&filesaver); 1556 add_doing(¬hingsaver); 1557 } 1558 1559 1560 int main(argc, argv) 1561 int argc; 1562 char *argv[]; 1563 { 1564 int doread, c, make_daemon = 0; 1565 char *prog; 1566 config_t config; 1567 1568 prog = strrchr(argv[0], '/'); 1569 if (prog == NULL) 1570 prog = argv[0]; 1571 else 1572 prog++; 1573 1574 initconfig(&config); 1575 1576 while ((c = getopt(argc, argv, 1577 "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) 1578 switch (c) 1579 { 1580 case 'a' : 1581 ipmonopts |= IPMON_LOGALL; 1582 config.logsrc[0].logtype = IPL_LOGIPF; 1583 config.logsrc[1].logtype = IPL_LOGNAT; 1584 config.logsrc[2].logtype = IPL_LOGSTATE; 1585 break; 1586 case 'b' : 1587 ipmonopts |= IPMON_LOGBODY; 1588 break; 1589 case 'B' : 1590 config.bfile = optarg; 1591 config.blog = fopen(optarg, "a"); 1592 break; 1593 case 'C' : 1594 config.cfile = optarg; 1595 break; 1596 case 'D' : 1597 make_daemon = 1; 1598 break; 1599 case 'f' : case 'I' : 1600 ipmonopts |= IPMON_FILTER; 1601 config.logsrc[0].logtype = IPL_LOGIPF; 1602 config.logsrc[0].file = optarg; 1603 break; 1604 case 'F' : 1605 flushlogs(config.logsrc[0].file, config.log); 1606 flushlogs(config.logsrc[1].file, config.log); 1607 flushlogs(config.logsrc[2].file, config.log); 1608 break; 1609 case 'L' : 1610 logfac = fac_findname(optarg); 1611 if (logfac == -1) { 1612 fprintf(stderr, 1613 "Unknown syslog facility '%s'\n", 1614 optarg); 1615 exit(1); 1616 } 1617 break; 1618 case 'n' : 1619 ipmonopts |= IPMON_RESOLVE; 1620 opts &= ~OPT_NORESOLVE; 1621 break; 1622 case 'N' : 1623 ipmonopts |= IPMON_NAT; 1624 config.logsrc[1].logtype = IPL_LOGNAT; 1625 config.logsrc[1].file = optarg; 1626 break; 1627 case 'o' : case 'O' : 1628 logopts(c == 'o', optarg); 1629 if (ipmonopts & IPMON_FILTER) 1630 config.logsrc[0].logtype = IPL_LOGIPF; 1631 if (ipmonopts & IPMON_NAT) 1632 config.logsrc[1].logtype = IPL_LOGNAT; 1633 if (ipmonopts & IPMON_STATE) 1634 config.logsrc[2].logtype = IPL_LOGSTATE; 1635 break; 1636 case 'p' : 1637 ipmonopts |= IPMON_PORTNUM; 1638 break; 1639 case 'P' : 1640 pidfile = optarg; 1641 break; 1642 case 's' : 1643 ipmonopts |= IPMON_SYSLOG; 1644 config.log = NULL; 1645 break; 1646 case 'S' : 1647 ipmonopts |= IPMON_STATE; 1648 config.logsrc[2].logtype = IPL_LOGSTATE; 1649 config.logsrc[2].file = optarg; 1650 break; 1651 case 't' : 1652 ipmonopts |= IPMON_TAIL; 1653 break; 1654 case 'v' : 1655 ipmonopts |= IPMON_VERBOSE; 1656 break; 1657 case 'x' : 1658 ipmonopts |= IPMON_HEXBODY; 1659 break; 1660 case 'X' : 1661 ipmonopts |= IPMON_HEXHDR; 1662 break; 1663 default : 1664 case 'h' : 1665 case '?' : 1666 usage(argv[0]); 1667 } 1668 1669 if (ipmonopts & IPMON_SYSLOG) 1670 openlog(prog, LOG_NDELAY|LOG_PID, logfac); 1671 1672 init_tabs(); 1673 if (config.cfile) 1674 if (load_config(config.cfile) == -1) { 1675 unload_config(); 1676 exit(1); 1677 } 1678 1679 /* 1680 * Default action is to only open the filter log file. 1681 */ 1682 if ((config.logsrc[0].logtype == -1) && 1683 (config.logsrc[0].logtype == -1) && 1684 (config.logsrc[0].logtype == -1)) 1685 config.logsrc[0].logtype = IPL_LOGIPF; 1686 1687 openlogs(&config); 1688 1689 if (!(ipmonopts & IPMON_SYSLOG)) { 1690 config.file = argv[optind]; 1691 config.log = config.file ? fopen(config.file, "a") : stdout; 1692 if (config.log == NULL) { 1693 (void) fprintf(stderr, "%s: fopen: %s\n", 1694 argv[optind], STRERROR(errno)); 1695 exit(1); 1696 /* NOTREACHED */ 1697 } 1698 setvbuf(config.log, NULL, _IONBF, 0); 1699 } else { 1700 config.log = NULL; 1701 } 1702 1703 if (make_daemon && 1704 ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { 1705 #ifdef BSD 1706 daemon(0, !(ipmonopts & IPMON_SYSLOG)); 1707 #else 1708 int pid; 1709 1710 switch (fork()) 1711 { 1712 case -1 : 1713 (void) fprintf(stderr, "%s: fork() failed: %s\n", 1714 argv[0], STRERROR(errno)); 1715 exit(1); 1716 /* NOTREACHED */ 1717 case 0 : 1718 break; 1719 default : 1720 exit(0); 1721 } 1722 1723 setsid(); 1724 if ((ipmonopts & IPMON_SYSLOG)) 1725 close(2); 1726 #endif /* !BSD */ 1727 close(0); 1728 close(1); 1729 write_pid(pidfile); 1730 } 1731 1732 signal(SIGHUP, handlehup); 1733 1734 for (doread = 1; doread; ) 1735 doread = read_loginfo(&config); 1736 1737 unload_config(); 1738 1739 return(0); 1740 /* NOTREACHED */ 1741 } 1742 1743 1744 static void openlogs(config_t *conf) 1745 { 1746 logsource_t *l; 1747 struct stat sb; 1748 int i; 1749 1750 for (i = 0; i < 3; i++) { 1751 l = &conf->logsrc[i]; 1752 if (l->logtype == -1) 1753 continue; 1754 if (!strcmp(l->file, "-")) 1755 l->fd = 0; 1756 else { 1757 if ((l->fd= open(l->file, O_RDONLY)) == -1) { 1758 (void) fprintf(stderr, 1759 "%s: open: %s\n", l->file, 1760 STRERROR(errno)); 1761 exit(1); 1762 /* NOTREACHED */ 1763 } 1764 1765 if (fstat(l->fd, &sb) == -1) { 1766 (void) fprintf(stderr, "%d: fstat: %s\n", 1767 l->fd, STRERROR(errno)); 1768 exit(1); 1769 /* NOTREACHED */ 1770 } 1771 1772 l->regular = !S_ISCHR(sb.st_mode); 1773 if (l->regular) 1774 l->size = sb.st_size; 1775 1776 FD_SET(l->fd, &conf->fdmr); 1777 if (l->fd > conf->maxfd) 1778 conf->maxfd = l->fd; 1779 } 1780 } 1781 } 1782 1783 1784 static int read_loginfo(config_t *conf) 1785 { 1786 iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; 1787 int n, tr, nr, i; 1788 logsource_t *l; 1789 fd_set fdr; 1790 1791 fdr = conf->fdmr; 1792 1793 n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); 1794 if (n == 0) 1795 return 1; 1796 if (n == -1) { 1797 if (errno == EINTR) 1798 return 1; 1799 return -1; 1800 } 1801 1802 for (i = 0, nr = 0; i < 3; i++) { 1803 l = &conf->logsrc[i]; 1804 1805 if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) 1806 continue; 1807 1808 tr = 0; 1809 if (l->regular) { 1810 tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); 1811 if (!tr && !(ipmonopts & IPMON_TAIL)) 1812 return 0; 1813 } 1814 1815 n = 0; 1816 tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); 1817 if (donehup) { 1818 if (conf->file != NULL) { 1819 if (conf->log != NULL) { 1820 fclose(conf->log); 1821 conf->log = NULL; 1822 } 1823 conf->log = fopen(conf->file, "a"); 1824 } 1825 1826 if (conf->bfile != NULL) { 1827 if (conf->blog != NULL) { 1828 fclose(conf->blog); 1829 conf->blog = NULL; 1830 } 1831 conf->blog = fopen(conf->bfile, "a"); 1832 } 1833 1834 init_tabs(); 1835 if (conf->cfile != NULL) 1836 load_config(conf->cfile); 1837 donehup = 0; 1838 } 1839 1840 switch (tr) 1841 { 1842 case -1 : 1843 if (ipmonopts & IPMON_SYSLOG) 1844 syslog(LOG_CRIT, "read: %m\n"); 1845 else { 1846 ipferror(l->fd, "read"); 1847 } 1848 return 0; 1849 case 1 : 1850 if (ipmonopts & IPMON_SYSLOG) 1851 syslog(LOG_CRIT, "aborting logging\n"); 1852 else if (conf->log != NULL) 1853 fprintf(conf->log, "aborting logging\n"); 1854 return 0; 1855 case 2 : 1856 break; 1857 case 0 : 1858 nr += tr; 1859 if (n > 0) { 1860 print_log(conf, l, (char *)buf, n); 1861 if (!(ipmonopts & IPMON_SYSLOG)) 1862 fflush(conf->log); 1863 } 1864 break; 1865 } 1866 } 1867 1868 if (!nr && (ipmonopts & IPMON_TAIL)) 1869 sleep(1); 1870 1871 return 1; 1872 } 1873