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