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 if (bp == NULL) { 925 perror("malloc"); 926 exit(1); 927 } 928 bcopy((char *)ipl, bp, blen); 929 if (bpo) { 930 free(bpo); 931 bpo = NULL; 932 } 933 buf = bp; 934 continue; 935 } 936 937 psize = ipl->ipl_dsize; 938 if (psize > blen) 939 break; 940 941 if (binarylog) { 942 fwrite(buf, psize, 1, binarylog); 943 fflush(binarylog); 944 } 945 946 if (logtype == IPL_LOGIPF) { 947 if (ipl->ipl_magic != IPL_MAGIC) { 948 /* invalid data or out of sync */ 949 break; 950 } 951 print_ipflog(log, buf, psize); 952 953 } else if (logtype == IPL_LOGNAT) { 954 if (ipl->ipl_magic != IPL_MAGIC) { 955 /* invalid data or out of sync */ 956 break; 957 } 958 print_natlog(log, buf, psize); 959 960 } else if (logtype == IPL_LOGSTATE) { 961 if (ipl->ipl_magic != IPL_MAGIC) { 962 /* invalid data or out of sync */ 963 break; 964 } 965 print_statelog(log, buf, psize); 966 } 967 968 blen -= psize; 969 buf += psize; 970 } 971 if (bp) 972 free(bp); 973 return; 974 } 975 976 977 static void print_ipflog(log, buf, blen) 978 FILE *log; 979 char *buf; 980 int blen; 981 { 982 tcphdr_t *tp; 983 struct icmp *ic; 984 struct icmp *icmp; 985 struct tm *tm; 986 char *t, *proto; 987 int i, v, lvl, res, len, off, plen, ipoff; 988 u_32_t *s, *d, cmdflags; 989 ip_t *ipc, *ip; 990 u_short hl, p; 991 ipflog_t *ipf; 992 iplog_t *ipl; 993 #ifdef USE_INET6 994 ip6_t *ip6; 995 #endif 996 997 ipl = (iplog_t *)buf; 998 ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 999 ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 1000 v = IP_V(ip); 1001 res = (opts & OPT_RESOLVE) ? 1 : 0; 1002 t = line; 1003 *t = '\0'; 1004 tm = get_tm(ipl->ipl_sec); 1005 1006 len = sizeof(line); 1007 if (!(opts & OPT_SYSLOG)) { 1008 (void) strftime(t, len, "%d/%m/%Y ", tm); 1009 i = strlen(t); 1010 len -= i; 1011 t += i; 1012 } 1013 (void) strftime(t, len, "%T", tm); 1014 t += strlen(t); 1015 (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 1016 t += strlen(t); 1017 if (ipl->ipl_count > 1) { 1018 (void) sprintf(t, "%dx ", ipl->ipl_count); 1019 t += strlen(t); 1020 } 1021 #if (defined(MENTAT) || \ 1022 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 1023 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) 1024 { 1025 char ifname[sizeof(ipf->fl_ifname) + 1]; 1026 1027 strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1028 ifname[sizeof(ipf->fl_ifname)] = '\0'; 1029 (void) sprintf(t, "%s", ifname); 1030 t += strlen(t); 1031 # if defined(MENTAT) 1032 if (isalpha(*(t - 1))) { 1033 sprintf(t, "%d", ipf->fl_unit); 1034 t += strlen(t); 1035 } 1036 # endif 1037 } 1038 #else 1039 for (len = 0; len < 3; len++) 1040 if (ipf->fl_ifname[len] == '\0') 1041 break; 1042 if (ipf->fl_ifname[len]) 1043 len++; 1044 (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); 1045 t += strlen(t); 1046 #endif 1047 if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0')) 1048 strcat(t, " @-1:"); 1049 else if (ipf->fl_group[0] == '\0') 1050 (void) strcpy(t, " @0:"); 1051 else 1052 (void) sprintf(t, " @%s:", ipf->fl_group); 1053 t += strlen(t); 1054 if (ipf->fl_rule == 0xffffffff) 1055 strcat(t, "-1 "); 1056 else 1057 (void) sprintf(t, "%u ", ipf->fl_rule + 1); 1058 t += strlen(t); 1059 1060 lvl = LOG_NOTICE; 1061 1062 if (ipf->fl_lflags & FI_SHORT) { 1063 *t++ = 'S'; 1064 lvl = LOG_ERR; 1065 } 1066 1067 cmdflags = ipf->fl_flags & FR_CMDMASK; 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 = 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, " frag %s%s%hu@%hu", 1222 ipoff & IP_MF ? "+" : "", 1223 ipoff & IP_DF ? "-" : "", 1224 i - (IP_HL(ipc) << 2), 1225 (ipoff & IP_OFFMASK) << 3); 1226 } 1227 } 1228 1229 } 1230 } else { 1231 (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1232 t += strlen(t); 1233 (void) sprintf(t, "%s PR %s len %hu (%hu)", 1234 hostname(res, v, d), proto, hl, plen); 1235 t += strlen(t); 1236 if (off & IP_OFFMASK) 1237 (void) sprintf(t, " frag %s%s%hu@%hu", 1238 ipoff & IP_MF ? "+" : "", 1239 ipoff & IP_DF ? "-" : "", 1240 plen - hl, (off & IP_OFFMASK) << 3); 1241 } 1242 t += strlen(t); 1243 1244 if (ipf->fl_flags & FR_KEEPSTATE) { 1245 (void) strcpy(t, " K-S"); 1246 t += strlen(t); 1247 } 1248 1249 if (ipf->fl_flags & FR_KEEPFRAG) { 1250 (void) strcpy(t, " K-F"); 1251 t += strlen(t); 1252 } 1253 1254 if (ipf->fl_dir == 0) 1255 strcpy(t, " IN"); 1256 else if (ipf->fl_dir == 1) 1257 strcpy(t, " OUT"); 1258 t += strlen(t); 1259 if (ipf->fl_tag) { 1260 sprintf(t, " tag %d", ipf->fl_tag); 1261 t += strlen(t); 1262 } 1263 printipflog: 1264 *t++ = '\n'; 1265 *t++ = '\0'; 1266 if (opts & OPT_SYSLOG) 1267 syslog(lvl, "%s", line); 1268 else 1269 (void) fprintf(log, "%s", line); 1270 if (opts & OPT_HEXHDR) 1271 dumphex(log, opts, buf, sizeof(iplog_t) + sizeof(*ipf)); 1272 if (opts & OPT_HEXBODY) 1273 dumphex(log, opts, (char *)ip, ipf->fl_plen + ipf->fl_hlen); 1274 else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) 1275 dumphex(log, opts, (char *)ip + ipf->fl_hlen, ipf->fl_plen); 1276 if (conf_file) 1277 check_action(buf, opts, line); 1278 } 1279 1280 1281 static void usage(prog) 1282 char *prog; 1283 { 1284 fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n", 1285 prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]", 1286 "[-P pidfile]", "[-S device]", "[-f device]", 1287 "filename"); 1288 exit(1); 1289 } 1290 1291 1292 static void write_pid(file) 1293 char *file; 1294 { 1295 FILE *fp = NULL; 1296 int fd; 1297 1298 if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1299 fp = fdopen(fd, "w"); 1300 if (fp == NULL) { 1301 close(fd); 1302 fprintf(stderr, 1303 "unable to open/create pid file: %s\n", file); 1304 return; 1305 } 1306 fprintf(fp, "%d", getpid()); 1307 fclose(fp); 1308 } 1309 } 1310 1311 1312 static void flushlogs(file, log) 1313 char *file; 1314 FILE *log; 1315 { 1316 int fd, flushed = 0; 1317 1318 if ((fd = open(file, O_RDWR)) == -1) { 1319 (void) fprintf(stderr, "%s: open: %s\n", 1320 file, STRERROR(errno)); 1321 exit(1); 1322 } 1323 1324 if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1325 printf("%d bytes flushed from log buffer\n", 1326 flushed); 1327 fflush(stdout); 1328 } else 1329 perror("SIOCIPFFB"); 1330 (void) close(fd); 1331 1332 if (flushed) { 1333 if (opts & OPT_SYSLOG) 1334 syslog(LOG_INFO, "%d bytes flushed from log\n", 1335 flushed); 1336 else if (log != stdout) 1337 fprintf(log, "%d bytes flushed from log\n", flushed); 1338 } 1339 } 1340 1341 1342 static void logopts(turnon, options) 1343 int turnon; 1344 char *options; 1345 { 1346 int flags = 0; 1347 char *s; 1348 1349 for (s = options; *s; s++) 1350 { 1351 switch (*s) 1352 { 1353 case 'N' : 1354 flags |= OPT_NAT; 1355 break; 1356 case 'S' : 1357 flags |= OPT_STATE; 1358 break; 1359 case 'I' : 1360 flags |= OPT_FILTER; 1361 break; 1362 default : 1363 fprintf(stderr, "Unknown log option %c\n", *s); 1364 exit(1); 1365 } 1366 } 1367 1368 if (turnon) 1369 opts |= flags; 1370 else 1371 opts &= ~(flags); 1372 } 1373 1374 1375 int main(argc, argv) 1376 int argc; 1377 char *argv[]; 1378 { 1379 struct stat sb; 1380 FILE *log = stdout; 1381 int fd[3], doread, n, i; 1382 int tr, nr, regular[3], c; 1383 int fdt[3], devices = 0, make_daemon = 0; 1384 char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; 1385 extern int optind; 1386 extern char *optarg; 1387 1388 fd[0] = fd[1] = fd[2] = -1; 1389 fdt[0] = fdt[1] = fdt[2] = -1; 1390 iplfile[0] = IPL_NAME; 1391 iplfile[1] = IPNAT_NAME; 1392 iplfile[2] = IPSTATE_NAME; 1393 1394 while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1) 1395 switch (c) 1396 { 1397 case 'a' : 1398 opts |= OPT_LOGALL; 1399 fdt[0] = IPL_LOGIPF; 1400 fdt[1] = IPL_LOGNAT; 1401 fdt[2] = IPL_LOGSTATE; 1402 break; 1403 case 'b' : 1404 opts |= OPT_LOGBODY; 1405 break; 1406 case 'B' : 1407 binarylogfile = optarg; 1408 binarylog = fopen(optarg, "a"); 1409 break; 1410 case 'C' : 1411 conf_file = optarg; 1412 break; 1413 case 'D' : 1414 make_daemon = 1; 1415 break; 1416 case 'f' : case 'I' : 1417 opts |= OPT_FILTER; 1418 fdt[0] = IPL_LOGIPF; 1419 iplfile[0] = optarg; 1420 break; 1421 case 'F' : 1422 flushlogs(iplfile[0], log); 1423 flushlogs(iplfile[1], log); 1424 flushlogs(iplfile[2], log); 1425 break; 1426 case 'n' : 1427 opts |= OPT_RESOLVE; 1428 break; 1429 case 'N' : 1430 opts |= OPT_NAT; 1431 fdt[1] = IPL_LOGNAT; 1432 iplfile[1] = optarg; 1433 break; 1434 case 'o' : case 'O' : 1435 logopts(c == 'o', optarg); 1436 fdt[0] = fdt[1] = fdt[2] = -1; 1437 if (opts & OPT_FILTER) 1438 fdt[0] = IPL_LOGIPF; 1439 if (opts & OPT_NAT) 1440 fdt[1] = IPL_LOGNAT; 1441 if (opts & OPT_STATE) 1442 fdt[2] = IPL_LOGSTATE; 1443 break; 1444 case 'p' : 1445 opts |= OPT_PORTNUM; 1446 break; 1447 case 'P' : 1448 pidfile = optarg; 1449 break; 1450 case 's' : 1451 s = strrchr(argv[0], '/'); 1452 if (s == NULL) 1453 s = argv[0]; 1454 else 1455 s++; 1456 openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); 1457 s = NULL; 1458 opts |= OPT_SYSLOG; 1459 log = NULL; 1460 break; 1461 case 'S' : 1462 opts |= OPT_STATE; 1463 fdt[2] = IPL_LOGSTATE; 1464 iplfile[2] = optarg; 1465 break; 1466 case 't' : 1467 opts |= OPT_TAIL; 1468 break; 1469 case 'v' : 1470 opts |= OPT_VERBOSE; 1471 break; 1472 case 'x' : 1473 opts |= OPT_HEXBODY; 1474 break; 1475 case 'X' : 1476 opts |= OPT_HEXHDR; 1477 break; 1478 default : 1479 case 'h' : 1480 case '?' : 1481 usage(argv[0]); 1482 } 1483 1484 init_tabs(); 1485 if (conf_file) 1486 if (load_config(conf_file) == -1) 1487 exit(1); 1488 1489 /* 1490 * Default action is to only open the filter log file. 1491 */ 1492 if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) 1493 fdt[0] = IPL_LOGIPF; 1494 1495 for (i = 0; i < 3; i++) { 1496 if (fdt[i] == -1) 1497 continue; 1498 if (!strcmp(iplfile[i], "-")) 1499 fd[i] = 0; 1500 else { 1501 if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { 1502 (void) fprintf(stderr, 1503 "%s: open: %s\n", iplfile[i], 1504 STRERROR(errno)); 1505 exit(1); 1506 /* NOTREACHED */ 1507 } 1508 if (fstat(fd[i], &sb) == -1) { 1509 (void) fprintf(stderr, "%d: fstat: %s\n", 1510 fd[i], STRERROR(errno)); 1511 exit(1); 1512 /* NOTREACHED */ 1513 } 1514 if (!(regular[i] = !S_ISCHR(sb.st_mode))) 1515 devices++; 1516 } 1517 } 1518 1519 if (!(opts & OPT_SYSLOG)) { 1520 logfile = argv[optind]; 1521 log = logfile ? fopen(logfile, "a") : stdout; 1522 if (log == NULL) { 1523 (void) fprintf(stderr, "%s: fopen: %s\n", 1524 argv[optind], STRERROR(errno)); 1525 exit(1); 1526 /* NOTREACHED */ 1527 } 1528 setvbuf(log, NULL, _IONBF, 0); 1529 } else 1530 log = NULL; 1531 1532 if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { 1533 #if BSD >= 199306 1534 daemon(0, !(opts & OPT_SYSLOG)); 1535 #else 1536 int pid; 1537 if ((pid = fork()) > 0) 1538 exit(0); 1539 if (pid < 0) { 1540 (void) fprintf(stderr, "%s: fork() failed: %s\n", 1541 argv[0], STRERROR(errno)); 1542 exit(1); 1543 /* NOTREACHED */ 1544 } 1545 setsid(); 1546 if ((opts & OPT_SYSLOG)) 1547 close(2); 1548 #endif /* !BSD */ 1549 close(0); 1550 close(1); 1551 } 1552 write_pid(pidfile); 1553 1554 signal(SIGHUP, handlehup); 1555 1556 for (doread = 1; doread; ) { 1557 nr = 0; 1558 1559 for (i = 0; i < 3; i++) { 1560 tr = 0; 1561 if (fdt[i] == -1) 1562 continue; 1563 if (!regular[i]) { 1564 if (ioctl(fd[i], FIONREAD, &tr) == -1) { 1565 if (opts & OPT_SYSLOG) 1566 syslog(LOG_CRIT, 1567 "ioctl(FIONREAD): %m"); 1568 else 1569 perror("ioctl(FIONREAD)"); 1570 exit(1); 1571 /* NOTREACHED */ 1572 } 1573 } else { 1574 tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); 1575 if (!tr && !(opts & OPT_TAIL)) 1576 doread = 0; 1577 } 1578 if (!tr) 1579 continue; 1580 nr += tr; 1581 1582 tr = read_log(fd[i], &n, buf, sizeof(buf)); 1583 if (donehup) { 1584 donehup = 0; 1585 if (newlog) { 1586 fclose(log); 1587 log = newlog; 1588 newlog = NULL; 1589 } 1590 if (newbinarylog) { 1591 fclose(binarylog); 1592 binarylog = newbinarylog; 1593 newbinarylog = NULL; 1594 } 1595 } 1596 1597 switch (tr) 1598 { 1599 case -1 : 1600 if (opts & OPT_SYSLOG) 1601 syslog(LOG_CRIT, "read: %m\n"); 1602 else 1603 perror("read"); 1604 doread = 0; 1605 break; 1606 case 1 : 1607 if (opts & OPT_SYSLOG) 1608 syslog(LOG_CRIT, "aborting logging\n"); 1609 else 1610 fprintf(log, "aborting logging\n"); 1611 doread = 0; 1612 break; 1613 case 2 : 1614 break; 1615 case 0 : 1616 if (n > 0) { 1617 print_log(fdt[i], log, buf, n); 1618 if (!(opts & OPT_SYSLOG)) 1619 fflush(log); 1620 } 1621 break; 1622 } 1623 } 1624 if (!nr && ((opts & OPT_TAIL) || devices)) 1625 sleep(1); 1626 } 1627 return(0); 1628 /* NOTREACHED */ 1629 } 1630