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