1 /* 2 * Copyright (C) 2001-2008 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 7 * Use is subject to license terms. 8 */ 9 10 #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->nlg_rule + 1); 741 t += strlen(t); 742 743 if (nl->nlg_type == NL_NEWMAP) 744 strcpy(t, "NAT:MAP "); 745 else if (nl->nlg_type == NL_NEWRDR) 746 strcpy(t, "NAT:RDR "); 747 else if (nl->nlg_type == NL_FLUSH) 748 strcpy(t, "NAT:FLUSH "); 749 else if (nl->nlg_type == NL_EXPIRE) 750 strcpy(t, "NAT:EXPIRE "); 751 else if (nl->nlg_type == NL_NEWBIMAP) 752 strcpy(t, "NAT:BIMAP "); 753 else if (nl->nlg_type == NL_NEWBLOCK) 754 strcpy(t, "NAT:MAPBLOCK "); 755 else if (nl->nlg_type == NL_CLONE) 756 strcpy(t, "NAT:CLONE "); 757 else 758 sprintf(t, "Type: %d ", nl->nlg_type); 759 t += strlen(t); 760 761 proto = getproto(nl->nlg_p); 762 763 (void) sprintf(t, "%s,%s <- -> ", hostname(res, nl->nlg_v, 764 (u_32_t *)&nl->nlg_inip), 765 portname(res, proto, (u_int)nl->nlg_inport)); 766 t += strlen(t); 767 (void) sprintf(t, "%s,%s ", hostname(res, nl->nlg_v, 768 (u_32_t *)&nl->nlg_outip), 769 portname(res, proto, (u_int)nl->nlg_outport)); 770 t += strlen(t); 771 (void) sprintf(t, "[%s,%s]", hostname(res, nl->nlg_v, 772 (u_32_t *)&nl->nlg_origip), 773 portname(res, proto, (u_int)nl->nlg_origport)); 774 t += strlen(t); 775 if (nl->nlg_type == NL_EXPIRE) { 776 #ifdef USE_QUAD_T 777 (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 778 (long long)nl->nlg_pkts[0], 779 (long long)nl->nlg_pkts[1], 780 (long long)nl->nlg_bytes[0], 781 (long long)nl->nlg_bytes[1]); 782 #else 783 (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 784 nl->nlg_pkts[0], nl->nlg_pkts[1], 785 nl->nlg_bytes[0], nl->nlg_bytes[1]); 786 #endif 787 t += strlen(t); 788 } 789 790 *t++ = '\n'; 791 *t++ = '\0'; 792 if (opts & OPT_SYSLOG) 793 syslog(LOG_INFO, "%s", line); 794 else 795 (void) fprintf(log, "%s", line); 796 } 797 798 799 static void print_statelog(log, buf, blen) 800 FILE *log; 801 char *buf; 802 int blen; 803 { 804 struct ipslog *sl; 805 iplog_t *ipl = (iplog_t *)buf; 806 char *t = line, *proto; 807 struct tm *tm; 808 int res, i, len; 809 810 sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 811 res = (opts & OPT_RESOLVE) ? 1 : 0; 812 tm = get_tm(ipl->ipl_sec); 813 len = sizeof(line); 814 if (!(opts & OPT_SYSLOG)) { 815 (void) strftime(t, len, "%d/%m/%Y ", tm); 816 i = strlen(t); 817 len -= i; 818 t += i; 819 } 820 (void) strftime(t, len, "%T", tm); 821 t += strlen(t); 822 (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 823 t += strlen(t); 824 825 if (sl->isl_type == ISL_NEW) 826 strcpy(t, "STATE:NEW "); 827 else if (sl->isl_type == ISL_CLONE) 828 strcpy(t, "STATE:CLONED "); 829 else if (sl->isl_type == ISL_EXPIRE) { 830 if ((sl->isl_p == IPPROTO_TCP) && 831 (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 832 sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 833 strcpy(t, "STATE:CLOSE "); 834 else 835 strcpy(t, "STATE:EXPIRE "); 836 } else if (sl->isl_type == ISL_FLUSH) 837 strcpy(t, "STATE:FLUSH "); 838 else if (sl->isl_type == ISL_INTERMEDIATE) 839 strcpy(t, "STATE:INTERMEDIATE "); 840 else if (sl->isl_type == ISL_REMOVE) 841 strcpy(t, "STATE:REMOVE "); 842 else if (sl->isl_type == ISL_KILLED) 843 strcpy(t, "STATE:KILLED "); 844 else 845 sprintf(t, "Type: %d ", sl->isl_type); 846 t += strlen(t); 847 848 proto = getproto(sl->isl_p); 849 850 if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 851 (void) sprintf(t, "%s,%s -> ", 852 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), 853 portname(res, proto, (u_int)sl->isl_sport)); 854 t += strlen(t); 855 (void) sprintf(t, "%s,%s PR %s", 856 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 857 portname(res, proto, (u_int)sl->isl_dport), proto); 858 } else if (sl->isl_p == IPPROTO_ICMP) { 859 (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 860 (u_32_t *)&sl->isl_src)); 861 t += strlen(t); 862 (void) sprintf(t, "%s PR icmp %d", 863 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 864 sl->isl_itype); 865 } else if (sl->isl_p == IPPROTO_ICMPV6) { 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 icmpv6 %d", 870 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 871 sl->isl_itype); 872 } else { 873 (void) sprintf(t, "%s -> ", 874 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); 875 t += strlen(t); 876 (void) sprintf(t, "%s PR %s", 877 hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 878 proto); 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 #ifdef PRId64 889 " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 890 " Pkts out %" PRId64 " Bytes out %" PRId64 891 " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 892 " Pkts out %" PRId64 " Bytes out %" PRId64, 893 #else 894 " 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", 895 #endif /* PRId64 */ 896 #else 897 " 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", 898 #endif 899 sl->isl_pkts[0], sl->isl_bytes[0], 900 sl->isl_pkts[1], sl->isl_bytes[1], 901 sl->isl_pkts[2], sl->isl_bytes[2], 902 sl->isl_pkts[3], sl->isl_bytes[3]); 903 904 t += strlen(t); 905 } 906 907 *t++ = '\n'; 908 *t++ = '\0'; 909 if (opts & OPT_SYSLOG) 910 syslog(LOG_INFO, "%s", line); 911 else 912 (void) fprintf(log, "%s", line); 913 } 914 915 916 static void print_log(logtype, log, buf, blen) 917 FILE *log; 918 char *buf; 919 int logtype, blen; 920 { 921 iplog_t *ipl; 922 char *bp = NULL, *bpo = NULL; 923 int psize; 924 925 while (blen > 0) { 926 ipl = (iplog_t *)buf; 927 if ((u_long)ipl & (sizeof(long)-1)) { 928 if (bp) 929 bpo = bp; 930 bp = (char *)malloc(blen); 931 if (bp == NULL) { 932 perror("malloc"); 933 exit(1); 934 } 935 bcopy((char *)ipl, bp, blen); 936 if (bpo) { 937 free(bpo); 938 bpo = NULL; 939 } 940 buf = bp; 941 continue; 942 } 943 944 psize = ipl->ipl_dsize; 945 if (psize > blen) 946 break; 947 948 if (binarylog) { 949 fwrite(buf, psize, 1, binarylog); 950 fflush(binarylog); 951 } 952 953 if (logtype == IPL_LOGIPF) { 954 if (ipl->ipl_magic == IPL_MAGIC) 955 print_ipflog(log, buf, psize); 956 957 } else if (logtype == IPL_LOGNAT) { 958 if (ipl->ipl_magic == IPL_MAGIC_NAT) 959 print_natlog(log, buf, psize); 960 961 } else if (logtype == IPL_LOGSTATE) { 962 if (ipl->ipl_magic == IPL_MAGIC_STATE) 963 print_statelog(log, buf, psize); 964 } 965 966 blen -= psize; 967 buf += psize; 968 } 969 if (bp) 970 free(bp); 971 return; 972 } 973 974 975 static void print_ipflog(log, buf, blen) 976 FILE *log; 977 char *buf; 978 int blen; 979 { 980 tcphdr_t *tp; 981 struct icmp *ic; 982 struct icmp *icmp; 983 struct tm *tm; 984 char *t, *proto; 985 int i, v, lvl, res, len, off, plen, ipoff, defaction; 986 ip_t *ipc, *ip; 987 u_32_t *s, *d; 988 u_short hl, p; 989 ipflog_t *ipf; 990 iplog_t *ipl; 991 #ifdef USE_INET6 992 ip6_t *ip6; 993 #endif 994 995 ipl = (iplog_t *)buf; 996 ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 997 ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 998 v = IP_V(ip); 999 res = (opts & OPT_RESOLVE) ? 1 : 0; 1000 t = line; 1001 *t = '\0'; 1002 tm = get_tm(ipl->ipl_sec); 1003 1004 len = sizeof(line); 1005 if (!(opts & OPT_SYSLOG)) { 1006 (void) strftime(t, len, "%d/%m/%Y ", tm); 1007 i = strlen(t); 1008 len -= i; 1009 t += i; 1010 } 1011 (void) strftime(t, len, "%T", tm); 1012 t += strlen(t); 1013 (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 1014 t += strlen(t); 1015 if (ipl->ipl_count > 1) { 1016 (void) sprintf(t, "%dx ", ipl->ipl_count); 1017 t += strlen(t); 1018 } 1019 #if (defined(MENTAT) || \ 1020 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 1021 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ 1022 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) 1023 { 1024 char ifname[sizeof(ipf->fl_ifname) + 1]; 1025 1026 strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1027 ifname[sizeof(ipf->fl_ifname)] = '\0'; 1028 (void) sprintf(t, "%s", ifname); 1029 t += strlen(t); 1030 # if defined(MENTAT) || defined(linux) 1031 if (ISALPHA(*(t - 1))) { 1032 sprintf(t, "%d", ipf->fl_unit); 1033 t += strlen(t); 1034 } 1035 # endif 1036 } 1037 #else 1038 for (len = 0; len < 3; len++) 1039 if (ipf->fl_ifname[len] == '\0') 1040 break; 1041 if (ipf->fl_ifname[len]) 1042 len++; 1043 (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); 1044 t += strlen(t); 1045 #endif 1046 #if defined(__sgi) || defined(_AIX51) || defined(__powerpc__) || \ 1047 defined(__arm__) 1048 if ((ipf->fl_group[0] == 255) && (ipf->fl_group[1] == '\0')) 1049 #else 1050 if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0')) 1051 #endif 1052 strcat(t, " @-1:"); 1053 else if (ipf->fl_group[0] == '\0') 1054 (void) strcpy(t, " @0:"); 1055 else 1056 (void) sprintf(t, " @%s:", ipf->fl_group); 1057 t += strlen(t); 1058 if (ipf->fl_rule == 0xffffffff) 1059 strcat(t, "-1 "); 1060 else 1061 (void) sprintf(t, "%u ", ipf->fl_rule + 1); 1062 t += strlen(t); 1063 1064 lvl = LOG_NOTICE; 1065 1066 if (ipf->fl_lflags & FI_SHORT) { 1067 *t++ = 'S'; 1068 lvl = LOG_ERR; 1069 } 1070 1071 if (FR_ISPASS(ipf->fl_flags)) { 1072 if (ipf->fl_flags & FR_LOGP) 1073 *t++ = 'p'; 1074 else 1075 *t++ = 'P'; 1076 } else if (FR_ISBLOCK(ipf->fl_flags)) { 1077 if (ipf->fl_flags & FR_LOGB) 1078 *t++ = 'b'; 1079 else 1080 *t++ = 'B'; 1081 lvl = LOG_WARNING; 1082 } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 1083 *t++ = 'L'; 1084 lvl = LOG_INFO; 1085 } else if (ipf->fl_flags & FF_LOGNOMATCH) { 1086 *t++ = 'n'; 1087 } else { 1088 *t++ = '?'; 1089 lvl = LOG_EMERG; 1090 } 1091 if (ipf->fl_loglevel != 0xffff) 1092 lvl = ipf->fl_loglevel; 1093 *t++ = ' '; 1094 *t = '\0'; 1095 1096 if (v == 6) { 1097 #ifdef USE_INET6 1098 off = 0; 1099 ipoff = 0; 1100 hl = sizeof(ip6_t); 1101 ip6 = (ip6_t *)ip; 1102 p = (u_short)ip6->ip6_nxt; 1103 s = (u_32_t *)&ip6->ip6_src; 1104 d = (u_32_t *)&ip6->ip6_dst; 1105 plen = hl + ntohs(ip6->ip6_plen); 1106 #else 1107 sprintf(t, "ipv6"); 1108 goto printipflog; 1109 #endif 1110 } else if (v == 4) { 1111 hl = IP_HL(ip) << 2; 1112 ipoff = ip->ip_off; 1113 off = ipoff & IP_OFFMASK; 1114 p = (u_short)ip->ip_p; 1115 s = (u_32_t *)&ip->ip_src; 1116 d = (u_32_t *)&ip->ip_dst; 1117 plen = ip->ip_len; 1118 } else { 1119 goto printipflog; 1120 } 1121 proto = getproto(p); 1122 1123 if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 1124 tp = (tcphdr_t *)((char *)ip + hl); 1125 if (!(ipf->fl_lflags & FI_SHORT)) { 1126 (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), 1127 portname(res, proto, (u_int)tp->th_sport)); 1128 t += strlen(t); 1129 (void) sprintf(t, "%s,%s PR %s len %hu %hu", 1130 hostname(res, v, d), 1131 portname(res, proto, (u_int)tp->th_dport), 1132 proto, hl, plen); 1133 t += strlen(t); 1134 1135 if (p == IPPROTO_TCP) { 1136 *t++ = ' '; 1137 *t++ = '-'; 1138 for (i = 0; tcpfl[i].value; i++) 1139 if (tp->th_flags & tcpfl[i].value) 1140 *t++ = tcpfl[i].flag; 1141 if (opts & OPT_VERBOSE) { 1142 (void) sprintf(t, " %lu %lu %hu", 1143 (u_long)(ntohl(tp->th_seq)), 1144 (u_long)(ntohl(tp->th_ack)), 1145 ntohs(tp->th_win)); 1146 t += strlen(t); 1147 } 1148 } 1149 *t = '\0'; 1150 } else { 1151 (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1152 t += strlen(t); 1153 (void) sprintf(t, "%s PR %s len %hu %hu", 1154 hostname(res, v, d), proto, hl, plen); 1155 } 1156 } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { 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 icmpv6 len %hu %hu icmpv6 %s", 1161 hostname(res, v, d), hl, plen, 1162 icmpname6(ic->icmp_type, ic->icmp_code)); 1163 } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { 1164 ic = (struct icmp *)((char *)ip + hl); 1165 (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1166 t += strlen(t); 1167 (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", 1168 hostname(res, v, d), hl, plen, 1169 icmpname(ic->icmp_type, ic->icmp_code)); 1170 if (ic->icmp_type == ICMP_UNREACH || 1171 ic->icmp_type == ICMP_SOURCEQUENCH || 1172 ic->icmp_type == ICMP_PARAMPROB || 1173 ic->icmp_type == ICMP_REDIRECT || 1174 ic->icmp_type == ICMP_TIMXCEED) { 1175 ipc = &ic->icmp_ip; 1176 i = ntohs(ipc->ip_len); 1177 /* 1178 * XXX - try to guess endian of ip_len in ICMP 1179 * returned data. 1180 */ 1181 if (i > 1500) 1182 i = ipc->ip_len; 1183 ipoff = ntohs(ipc->ip_off); 1184 proto = getproto(ipc->ip_p); 1185 1186 if (!(ipoff & IP_OFFMASK) && 1187 ((ipc->ip_p == IPPROTO_TCP) || 1188 (ipc->ip_p == IPPROTO_UDP))) { 1189 tp = (tcphdr_t *)((char *)ipc + hl); 1190 t += strlen(t); 1191 (void) sprintf(t, " for %s,%s -", 1192 HOSTNAME_V4(res, ipc->ip_src), 1193 portname(res, proto, 1194 (u_int)tp->th_sport)); 1195 t += strlen(t); 1196 (void) sprintf(t, " %s,%s PR %s len %hu %hu", 1197 HOSTNAME_V4(res, ipc->ip_dst), 1198 portname(res, proto, 1199 (u_int)tp->th_dport), 1200 proto, IP_HL(ipc) << 2, i); 1201 } else if (!(ipoff & IP_OFFMASK) && 1202 (ipc->ip_p == IPPROTO_ICMP)) { 1203 icmp = (icmphdr_t *)((char *)ipc + hl); 1204 1205 t += strlen(t); 1206 (void) sprintf(t, " for %s -", 1207 HOSTNAME_V4(res, ipc->ip_src)); 1208 t += strlen(t); 1209 (void) sprintf(t, 1210 " %s PR icmp len %hu %hu icmp %d/%d", 1211 HOSTNAME_V4(res, ipc->ip_dst), 1212 IP_HL(ipc) << 2, i, 1213 icmp->icmp_type, icmp->icmp_code); 1214 } else { 1215 t += strlen(t); 1216 (void) sprintf(t, " for %s -", 1217 HOSTNAME_V4(res, ipc->ip_src)); 1218 t += strlen(t); 1219 (void) sprintf(t, " %s PR %s len %hu (%hu)", 1220 HOSTNAME_V4(res, ipc->ip_dst), proto, 1221 IP_HL(ipc) << 2, i); 1222 t += strlen(t); 1223 if (ipoff & IP_OFFMASK) { 1224 (void) sprintf(t, 1225 "(frag %d:%hu@%hu%s%s)", 1226 ntohs(ipc->ip_id), 1227 i - (IP_HL(ipc) << 2), 1228 (ipoff & IP_OFFMASK) << 3, 1229 ipoff & IP_MF ? "+" : "", 1230 ipoff & IP_DF ? "-" : ""); 1231 } 1232 } 1233 1234 } 1235 } else { 1236 (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1237 t += strlen(t); 1238 (void) sprintf(t, "%s PR %s len %hu (%hu)", 1239 hostname(res, v, d), proto, hl, plen); 1240 t += strlen(t); 1241 if (off & IP_OFFMASK) 1242 (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", 1243 ntohs(ip->ip_id), 1244 plen - hl, (off & IP_OFFMASK) << 3, 1245 ipoff & IP_MF ? "+" : "", 1246 ipoff & IP_DF ? "-" : ""); 1247 } 1248 t += strlen(t); 1249 1250 printipflog: 1251 if (ipf->fl_flags & FR_KEEPSTATE) { 1252 (void) strcpy(t, " K-S"); 1253 t += strlen(t); 1254 } 1255 1256 if (ipf->fl_flags & FR_KEEPFRAG) { 1257 (void) strcpy(t, " K-F"); 1258 t += strlen(t); 1259 } 1260 1261 if (ipf->fl_dir == 0) 1262 strcpy(t, " IN"); 1263 else if (ipf->fl_dir == 1) 1264 strcpy(t, " OUT"); 1265 t += strlen(t); 1266 if (ipf->fl_logtag != 0) { 1267 sprintf(t, " log-tag %d", ipf->fl_logtag); 1268 t += strlen(t); 1269 } 1270 if (ipf->fl_nattag.ipt_num[0] != 0) { 1271 strcpy(t, " nat-tag "); 1272 t += strlen(t); 1273 strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 1274 t += strlen(t); 1275 } 1276 if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 1277 strcpy(t, " low-ttl"); 1278 t += 8; 1279 } 1280 if ((ipf->fl_lflags & FI_OOW) != 0) { 1281 strcpy(t, " OOW"); 1282 t += 4; 1283 } 1284 if ((ipf->fl_lflags & FI_BAD) != 0) { 1285 strcpy(t, " bad"); 1286 t += 4; 1287 } 1288 if ((ipf->fl_lflags & FI_NATED) != 0) { 1289 strcpy(t, " NAT"); 1290 t += 4; 1291 } 1292 if ((ipf->fl_lflags & FI_BADNAT) != 0) { 1293 strcpy(t, " bad-NAT"); 1294 t += 8; 1295 } 1296 if ((ipf->fl_lflags & FI_BADSRC) != 0) { 1297 strcpy(t, " bad-src"); 1298 t += 8; 1299 } 1300 if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 1301 strcpy(t, " multicast"); 1302 t += 10; 1303 } 1304 if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 1305 strcpy(t, " broadcast"); 1306 t += 10; 1307 } 1308 if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 1309 FI_MBCAST) { 1310 strcpy(t, " mbcast"); 1311 t += 7; 1312 } 1313 *t++ = '\n'; 1314 *t++ = '\0'; 1315 defaction = 0; 1316 if (conf_file != NULL) 1317 defaction = check_action(buf, line, opts, lvl); 1318 if (defaction == 0) { 1319 if (opts & OPT_SYSLOG) 1320 syslog(lvl, "%s", line); 1321 else 1322 (void) fprintf(log, "%s", line); 1323 if (opts & OPT_HEXHDR) 1324 dumphex(log, opts, buf, 1325 sizeof(iplog_t) + sizeof(*ipf)); 1326 if (opts & OPT_HEXBODY) 1327 dumphex(log, opts, (char *)ip, 1328 ipf->fl_plen + ipf->fl_hlen); 1329 else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) 1330 dumphex(log, opts, (char *)ip + ipf->fl_hlen, 1331 ipf->fl_plen); 1332 } 1333 } 1334 1335 1336 static void usage(prog) 1337 char *prog; 1338 { 1339 fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n", 1340 prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]", 1341 "[-P pidfile]", "[-S device]", "[-f device]", 1342 "filename"); 1343 exit(1); 1344 } 1345 1346 1347 static void write_pid(file) 1348 char *file; 1349 { 1350 FILE *fp = NULL; 1351 int fd; 1352 1353 if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1354 fp = fdopen(fd, "w"); 1355 if (fp == NULL) { 1356 close(fd); 1357 fprintf(stderr, 1358 "unable to open/create pid file: %s\n", file); 1359 return; 1360 } 1361 fprintf(fp, "%d", getpid()); 1362 fclose(fp); 1363 } 1364 } 1365 1366 1367 static void flushlogs(file, log) 1368 char *file; 1369 FILE *log; 1370 { 1371 int fd, flushed = 0; 1372 1373 if ((fd = open(file, O_RDWR)) == -1) { 1374 (void) fprintf(stderr, "%s: open: %s\n", 1375 file, STRERROR(errno)); 1376 exit(1); 1377 } 1378 1379 if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1380 printf("%d bytes flushed from log buffer\n", 1381 flushed); 1382 fflush(stdout); 1383 } else 1384 perror("SIOCIPFFB"); 1385 (void) close(fd); 1386 1387 if (flushed) { 1388 if (opts & OPT_SYSLOG) 1389 syslog(LOG_INFO, "%d bytes flushed from log\n", 1390 flushed); 1391 else if (log != stdout) 1392 fprintf(log, "%d bytes flushed from log\n", flushed); 1393 } 1394 } 1395 1396 1397 static void logopts(turnon, options) 1398 int turnon; 1399 char *options; 1400 { 1401 int flags = 0; 1402 char *s; 1403 1404 for (s = options; *s; s++) 1405 { 1406 switch (*s) 1407 { 1408 case 'N' : 1409 flags |= OPT_NAT; 1410 break; 1411 case 'S' : 1412 flags |= OPT_STATE; 1413 break; 1414 case 'I' : 1415 flags |= OPT_FILTER; 1416 break; 1417 default : 1418 fprintf(stderr, "Unknown log option %c\n", *s); 1419 exit(1); 1420 } 1421 } 1422 1423 if (turnon) 1424 opts |= flags; 1425 else 1426 opts &= ~(flags); 1427 } 1428 1429 1430 int main(argc, argv) 1431 int argc; 1432 char *argv[]; 1433 { 1434 struct stat sb; 1435 FILE *log = stdout; 1436 FILE *fp; 1437 int fd[3], doread, n, i; 1438 int tr, nr, regular[3], c; 1439 int fdt[3], devices = 0, make_daemon = 0; 1440 char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; 1441 extern int optind; 1442 extern char *optarg; 1443 1444 fd[0] = fd[1] = fd[2] = -1; 1445 fdt[0] = fdt[1] = fdt[2] = -1; 1446 iplfile[0] = IPL_NAME; 1447 iplfile[1] = IPNAT_NAME; 1448 iplfile[2] = IPSTATE_NAME; 1449 1450 while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1) 1451 switch (c) 1452 { 1453 case 'a' : 1454 opts |= OPT_LOGALL; 1455 fdt[0] = IPL_LOGIPF; 1456 fdt[1] = IPL_LOGNAT; 1457 fdt[2] = IPL_LOGSTATE; 1458 break; 1459 case 'b' : 1460 opts |= OPT_LOGBODY; 1461 break; 1462 case 'B' : 1463 binarylogfile = optarg; 1464 binarylog = fopen(optarg, "a"); 1465 break; 1466 case 'C' : 1467 conf_file = optarg; 1468 break; 1469 case 'D' : 1470 make_daemon = 1; 1471 break; 1472 case 'f' : case 'I' : 1473 opts |= OPT_FILTER; 1474 fdt[0] = IPL_LOGIPF; 1475 iplfile[0] = optarg; 1476 break; 1477 case 'F' : 1478 flushlogs(iplfile[0], log); 1479 flushlogs(iplfile[1], log); 1480 flushlogs(iplfile[2], log); 1481 break; 1482 case 'n' : 1483 opts |= OPT_RESOLVE; 1484 break; 1485 case 'N' : 1486 opts |= OPT_NAT; 1487 fdt[1] = IPL_LOGNAT; 1488 iplfile[1] = optarg; 1489 break; 1490 case 'o' : case 'O' : 1491 logopts(c == 'o', optarg); 1492 fdt[0] = fdt[1] = fdt[2] = -1; 1493 if (opts & OPT_FILTER) 1494 fdt[0] = IPL_LOGIPF; 1495 if (opts & OPT_NAT) 1496 fdt[1] = IPL_LOGNAT; 1497 if (opts & OPT_STATE) 1498 fdt[2] = IPL_LOGSTATE; 1499 break; 1500 case 'p' : 1501 opts |= OPT_PORTNUM; 1502 break; 1503 case 'P' : 1504 pidfile = optarg; 1505 break; 1506 case 's' : 1507 s = strrchr(argv[0], '/'); 1508 if (s == NULL) 1509 s = argv[0]; 1510 else 1511 s++; 1512 openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); 1513 s = NULL; 1514 opts |= OPT_SYSLOG; 1515 log = NULL; 1516 break; 1517 case 'S' : 1518 opts |= OPT_STATE; 1519 fdt[2] = IPL_LOGSTATE; 1520 iplfile[2] = optarg; 1521 break; 1522 case 't' : 1523 opts |= OPT_TAIL; 1524 break; 1525 case 'v' : 1526 opts |= OPT_VERBOSE; 1527 break; 1528 case 'x' : 1529 opts |= OPT_HEXBODY; 1530 break; 1531 case 'X' : 1532 opts |= OPT_HEXHDR; 1533 break; 1534 default : 1535 case 'h' : 1536 case '?' : 1537 usage(argv[0]); 1538 } 1539 1540 init_tabs(); 1541 if (conf_file) 1542 if (load_config(conf_file) == -1) 1543 exit(1); 1544 1545 /* 1546 * Default action is to only open the filter log file. 1547 */ 1548 if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) 1549 fdt[0] = IPL_LOGIPF; 1550 1551 for (i = 0; i < 3; i++) { 1552 if (fdt[i] == -1) 1553 continue; 1554 if (!strcmp(iplfile[i], "-")) 1555 fd[i] = 0; 1556 else { 1557 if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { 1558 (void) fprintf(stderr, 1559 "%s: open: %s\n", iplfile[i], 1560 STRERROR(errno)); 1561 exit(1); 1562 /* NOTREACHED */ 1563 } 1564 if (fstat(fd[i], &sb) == -1) { 1565 (void) fprintf(stderr, "%d: fstat: %s\n", 1566 fd[i], STRERROR(errno)); 1567 exit(1); 1568 /* NOTREACHED */ 1569 } 1570 if (!(regular[i] = !S_ISCHR(sb.st_mode))) 1571 devices++; 1572 } 1573 } 1574 1575 if (!(opts & OPT_SYSLOG)) { 1576 logfile = argv[optind]; 1577 log = logfile ? fopen(logfile, "a") : stdout; 1578 if (log == NULL) { 1579 (void) fprintf(stderr, "%s: fopen: %s\n", 1580 argv[optind], STRERROR(errno)); 1581 exit(1); 1582 /* NOTREACHED */ 1583 } 1584 setvbuf(log, NULL, _IONBF, 0); 1585 } else 1586 log = NULL; 1587 1588 if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { 1589 #if BSD >= 199306 1590 daemon(0, !(opts & OPT_SYSLOG)); 1591 #else 1592 int pid; 1593 if ((pid = fork()) > 0) 1594 exit(0); 1595 if (pid < 0) { 1596 (void) fprintf(stderr, "%s: fork() failed: %s\n", 1597 argv[0], STRERROR(errno)); 1598 exit(1); 1599 /* NOTREACHED */ 1600 } 1601 setsid(); 1602 if ((opts & OPT_SYSLOG)) 1603 close(2); 1604 #endif /* !BSD */ 1605 close(0); 1606 close(1); 1607 } 1608 write_pid(pidfile); 1609 1610 signal(SIGHUP, handlehup); 1611 1612 for (doread = 1; doread; ) { 1613 nr = 0; 1614 1615 for (i = 0; i < 3; i++) { 1616 tr = 0; 1617 if (fdt[i] == -1) 1618 continue; 1619 if (!regular[i]) { 1620 if (ioctl(fd[i], FIONREAD, &tr) == -1) { 1621 if (opts & OPT_SYSLOG) 1622 syslog(LOG_CRIT, 1623 "ioctl(FIONREAD): %m"); 1624 else 1625 perror("ioctl(FIONREAD)"); 1626 exit(1); 1627 /* NOTREACHED */ 1628 } 1629 } else { 1630 tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); 1631 if (!tr && !(opts & OPT_TAIL)) 1632 doread = 0; 1633 } 1634 if (!tr) 1635 continue; 1636 nr += tr; 1637 1638 tr = read_log(fd[i], &n, buf, sizeof(buf)); 1639 if (donehup) { 1640 if (logfile && (fp = fopen(logfile, "a"))) { 1641 fclose(log); 1642 log = fp; 1643 } 1644 if (binarylogfile && (fp = fopen(binarylogfile, "a"))) { 1645 fclose(binarylog); 1646 binarylog = fp; 1647 } 1648 init_tabs(); 1649 if (conf_file != NULL) 1650 load_config(conf_file); 1651 donehup = 0; 1652 } 1653 1654 switch (tr) 1655 { 1656 case -1 : 1657 if (opts & OPT_SYSLOG) 1658 syslog(LOG_CRIT, "read: %m\n"); 1659 else 1660 perror("read"); 1661 doread = 0; 1662 break; 1663 case 1 : 1664 if (opts & OPT_SYSLOG) 1665 syslog(LOG_CRIT, "aborting logging\n"); 1666 else 1667 fprintf(log, "aborting logging\n"); 1668 doread = 0; 1669 break; 1670 case 2 : 1671 break; 1672 case 0 : 1673 if (n > 0) { 1674 print_log(fdt[i], log, buf, n); 1675 if (!(opts & OPT_SYSLOG)) 1676 fflush(log); 1677 } 1678 break; 1679 } 1680 } 1681 if (!nr && ((opts & OPT_TAIL) || devices)) 1682 sleep(1); 1683 } 1684 return(0); 1685 /* NOTREACHED */ 1686 } 1687