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