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