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