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