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