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