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