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