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