diff options
author | dgregor <dgregor@cvs.openbsd.org> | 1998-01-26 04:17:12 +0000 |
---|---|---|
committer | dgregor <dgregor@cvs.openbsd.org> | 1998-01-26 04:17:12 +0000 |
commit | fe0239590c82ea51b1a09fd58cde9f1635ceab89 (patch) | |
tree | af8e00e22aa869bee7596358bc05686c76370f51 /usr.sbin/ipmon | |
parent | a344d388d075c3e901494684772107ed51830e00 (diff) |
IPF 3.2.3
Diffstat (limited to 'usr.sbin/ipmon')
-rw-r--r-- | usr.sbin/ipmon/ipmon.8 | 69 | ||||
-rw-r--r-- | usr.sbin/ipmon/ipmon.c | 768 |
2 files changed, 569 insertions, 268 deletions
diff --git a/usr.sbin/ipmon/ipmon.8 b/usr.sbin/ipmon/ipmon.8 index ff2f021e30b..7db99255734 100644 --- a/usr.sbin/ipmon/ipmon.8 +++ b/usr.sbin/ipmon/ipmon.8 @@ -1,12 +1,23 @@ +.\" $OpenBSD: ipmon.8,v 1.4 1998/01/26 04:16:46 dgregor Exp $ .TH ipmon 8 .SH NAME ipmon \- monitors /dev/ipl for logged packets .SH SYNOPSIS .B ipmon [ -.B \-sfN +.B \-aFhnstvxX ] [ -<filename> +.B "\-o [NSI]" +] [ +.B "\-O [NSI]" +] [ +.B "\-N <device>" +] [ +.B "\-S <device>" +] [ +.B "\-f <device>" +] [ +.B <filename> ] .SH DESCRIPTION .LP @@ -20,9 +31,45 @@ via syslog have the day, month and year removed from the message, but the time (including microseconds), as recorded in the log, is still included. .SH OPTIONS .TP +.B \-a +Open all of the device logfiles for reading log entries from. All entries +are displayed to the same output 'device' (stderr or syslog). +.TP +.B "\-f <device>" +specify an alternative device/file from which to read the log information +for normal IP Filter log records. +.TP +.B \-F +Flush the current packet log buffer. The number of bytes flushed is displayed, +even should the result be zero. +.TP +.B "\-N <device>" +Set the logfile to be opened for reading NAT log records from to <device>. +.TP +.B \-n +IP addresses and port numbers will be mapped, where possible, back into +hostnames and service names. +.TP +.B "\-N <device>" +Set the logfile to be opened for reading NAT log records from to <device>. +.TP +.B \-o +Specify which log files to actually read data from. N - NAT logfile, +S - State logfile, I - normal IP Filter logfile. The \fB-a\fP option is +equivalent to using \fB-o NSI\fP. +.TP +.B \-O +Specify which log files you do not wish to read from. This is most sensibly +used with the \fB-a\fP. Letters available as paramters to this are the same +as for \fB-o\fP. +.TP .B \-s Packet information read in will be sent through syslogd rather than saved to a file. The following levels are used: +.TP +.B "\-S <device>" +Set the logfile to be opened for reading state log records from to <device>. +.TP .IP .B LOG_INFO \- packets logged using the "log" keyword as the action rather @@ -38,13 +85,17 @@ than pass or block. \- packets which have been logged and which can be considered "short". .TP -.B \-f -Flush the current packet log buffer. The number of bytes flushed is displayed, -even should the result be zero. +.B \-S +Treat the logfile as being composed of state log records. .TP -.B \-N -IP addresses and port numbers will be mapped, where possible, back into -hostnames and service names. +.B \-t +read the input file/device in a manner akin to tail(1). +.TP +.B \-x +show the packet data in hex. +.TP +.B \-X +show the log header record data in hex. .SH DIAGNOSTICS \fBipmon\fP expects data that it reads to be consistent with how it should be saved and will abort if it fails an assertion which detects an anomaly in the @@ -52,5 +103,5 @@ recorded data. .SH FILES /dev/ipl .SH SEE ALSO -ipf(1), ipfstat(1) +ipf(8), ipfstat(8) .SH BUGS diff --git a/usr.sbin/ipmon/ipmon.c b/usr.sbin/ipmon/ipmon.c index e882089b9b8..b293bfbd35c 100644 --- a/usr.sbin/ipmon/ipmon.c +++ b/usr.sbin/ipmon/ipmon.c @@ -1,51 +1,73 @@ +/* $OpenBSD: ipmon.c,v 1.11 1998/01/26 04:16:47 dgregor Exp $ */ /* - * (C)opyright 1993-1996 by Darren Reed. + * Copyright (C) 1993-1997 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. */ +#if !defined(lint) +static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-1997 Darren Reed"; +static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.11 1998/01/26 04:16:47 dgregor Exp $"; +#endif #include <stdio.h> -#include <assert.h> #include <unistd.h> -#include <fcntl.h> #include <string.h> -#include <stdlib.h> -#include <syslog.h> -#include <sys/errno.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/param.h> -#include <sys/uio.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> #if !defined(__SVR4) && !defined(__svr4__) +#include <strings.h> #include <sys/dir.h> -#include <sys/mbuf.h> #else +#include <sys/filio.h> #include <sys/byteorder.h> #endif -#include <sys/protosw.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/time.h> +#include <stdlib.h> +#include <stddef.h> #include <sys/socket.h> -#include <sys/user.h> - -#include <net/if.h> +#include <sys/ioctl.h> #include <netinet/in.h> #include <netinet/in_systm.h> +#include <net/if.h> #include <netinet/ip.h> -#include <netinet/ip_var.h> -#include <netinet/tcp.h> -#include <netinet/tcpip.h> -#include <netinet/ip_icmp.h> #include <netdb.h> #include <arpa/inet.h> -#include <ctype.h> +#include <arpa/nameser.h> +#include <resolv.h> -#if !defined(lint) && defined(LIBC_SCCS) -static char rcsid[] = "$Id: ipmon.c,v 1.10 1997/07/22 17:00:05 kstailey Exp $"; +#include <sys/uio.h> +#ifndef linux +# include <sys/protosw.h> +# include <sys/user.h> +# include <netinet/ip_var.h> #endif +#include <netinet/tcp.h> +#include <netinet/ip_icmp.h> + +#include <ctype.h> +#include <syslog.h> + #include "ip_fil_compat.h" +#include <netinet/tcpip.h> #include "ip_fil.h" +#include "ip_proxy.h" +#include "ip_nat.h" +#include "ip_state.h" + + +#if defined(sun) && !defined(SOLARIS2) +#define STRERROR(x) sys_errlist[x] +extern char *sys_errlist[]; +#else +#define STRERROR(x) strerror(x) +#endif struct flags { @@ -65,158 +87,50 @@ struct flags tcpfl[] = { static char line[2048]; -static void printpacket(), dumphex(); static int opts = 0; - -#define OPT_SYSLOG 0x01 -#define OPT_RESOLVE 0x02 -#define OPT_HEXBODY 0x04 -#define OPT_VERBOSE 0x08 -#define OPT_HEXHDR 0x10 +static void usage __P((char *)); +static void flushlogs __P((char *, FILE *)); +static void print_log __P((int, FILE *, char *, int)); +static void print_ipflog __P((FILE *, char *, int)); +static void print_natlog __P((FILE *, char *, int)); +static void print_statelog __P((FILE *, char *, int)); +static void dumphex __P((FILE *, u_char *, int)); +static int read_log __P((int, int *, char *, int, FILE *)); +char *hostname __P((int, struct in_addr)); +char *portname __P((int, char *, u_short)); +int main __P((int, char *[])); + + +#define OPT_SYSLOG 0x001 +#define OPT_RESOLVE 0x002 +#define OPT_HEXBODY 0x004 +#define OPT_VERBOSE 0x008 +#define OPT_HEXHDR 0x010 +#define OPT_TAIL 0x020 +#define OPT_NAT 0x080 +#define OPT_STATE 0x100 +#define OPT_FILTER 0x200 +#define OPT_PORTNUM 0x400 +#define OPT_ALL (OPT_NAT|OPT_STATE|OPT_FILTER) #ifndef LOGFAC #define LOGFAC LOG_LOCAL0 #endif -void printiplci(icp) -struct ipl_ci *icp; -{ - printf("sec %ld usec %ld hlen %d plen %d\n", icp->sec, icp->usec, - icp->hlen, icp->plen); -} - - -void resynclog(fd, iplcp, log) -int fd; -struct ipl_ci *iplcp; -FILE *log; -{ - time_t now; - char *s = NULL; - int len, nr = 0; - - do { - if (s) { - s = (char *)&iplcp->sec; - if (opts & OPT_SYSLOG) { - syslog(LOG_INFO, "Sync bytes:"); - syslog(LOG_INFO, " %02x %02x %02x %02x", - *s, *(s+1), *(s+2), *(s+3)); - syslog(LOG_INFO, " %02x %02x %02x %02x\n", - *(s+4), *(s+5), *(s+6), *(s+7)); - } else { - fprintf(log, "Sync bytes:"); - fprintf(log, " %02x %02x %02x %02x", - *s, *(s+1), *(s+2), *(s+3)); - fprintf(log, " %02x %02x %02x %02x\n", - *(s+4), *(s+5), *(s+6), *(s+7)); - } - } - do { - s = (char *)&iplcp->sec; - len = sizeof(iplcp->sec); - while (len) { - switch ((nr = read(fd, s, len))) - { - case -1: - case 0: - return; - default : - s += nr; - len -= nr; - now = time(NULL); - break; - } - } - } while ((now < iplcp->sec) || - ((iplcp->sec - now) > (86400*5))); - - len = sizeof(iplcp->usec); - while (len) { - switch ((nr = read(fd, s, len))) - { - case -1: - case 0: - return; - default : - s += nr; - len -= nr; - break; - } - } - } while (iplcp->usec > 1000000); - len = sizeof(*iplcp) - sizeof(iplcp->sec) - sizeof(iplcp->usec); - while (len) { - switch ((nr = read(fd, s, len))) - { - case -1: - case 0: - return; - default : - s += nr; - len -= nr; - break; - } - } -} - - -int readlogentry(fd, lenp, buf, bufsize, log) +static int read_log(fd, lenp, buf, bufsize, log) int fd, bufsize, *lenp; char *buf; FILE *log; { - struct ipl_ci *icp = (struct ipl_ci *)buf; - time_t now; - char *s; - int len, n = bufsize, tr = sizeof(struct ipl_ci), nr; - - if (bufsize < tr) - return 1; - for (s = buf; (n > 0) && (tr > 0); s += nr, n -= nr) { - nr = read(fd, s, tr); - if (nr > 0) - tr -= nr; - else - return -1; - } - - now = time(NULL); - if ((icp->hlen > 92) || (now < icp->sec) || - ((now - icp->sec) > (86400*5))) { - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "Out of sync! (1,%x)\n", now); - else - fprintf(log, "Out of sync! (1,%x)\n", now); - dumphex(log, buf, sizeof(struct ipl_ci)); - resynclog(fd, icp, log); - } - - - len = (int)((u_int)icp->plen); - if (len > 128 || len < 0) { - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "Out of sync! (2,%d)\n", len); - else - fprintf(log, "Out of sync! (2,%d)\n", len); - dumphex(log, buf, sizeof(struct ipl_ci)); - resynclog(fd, icp, log); - } - - - tr = icp->hlen + icp->plen; - if (n < tr) - return 1; - - for (; (n > 0) && (tr > 0); s += nr, n-= nr) { - nr = read(fd, s, tr); - if (nr > 0) - tr -= nr; - else - return -1; - } - *lenp = s - buf; + int nr; + + nr = read(fd, buf, bufsize); + if (!nr) + return 2; + if ((nr < 0) && (errno != EINTR)) + return -1; + *lenp = nr; return 0; } @@ -245,7 +159,7 @@ u_short port; struct servent *serv; (void) sprintf(pname, "%hu", htons(port)); - if (!res) + if (!res || (opts & OPT_PORTNUM)) return pname; serv = getservbyport((int)port, proto); if (!serv) @@ -267,15 +181,18 @@ int len; if (j && !(j & 0xf)) { *t++ = '\n'; *t = '\0'; - fputs(line, log); + if (!(opts & OPT_SYSLOG)) + fputs(line, stdout); + else + syslog(LOG_INFO, "%s", line); t = (u_char *)line; *t = '\0'; } - sprintf(t, "%02x", *s & 0xff); + sprintf((char *)t, "%02x", *s & 0xff); t += 2; if (!((j + 1) & 0xf)) { s -= 15; - sprintf(t, " "); + sprintf((char *)t, " "); t += 8; for (k = 16; k; k--, s++) *t++ = (isprint(*s) ? *s : '.'); @@ -292,7 +209,7 @@ int len; *t++ = ' '; *t++ = ' '; } - sprintf(t, " "); + sprintf((char *)t, " "); t += 7; s -= j & 0xf; for (k = j & 0xf; k; k--, s++) @@ -300,12 +217,183 @@ int len; *t++ = '\n'; *t = '\0'; } - fputs(line, log); - fflush(log); + if (!(opts & OPT_SYSLOG)) { + fputs(line, stdout); + fflush(stdout); + } else + syslog(LOG_INFO, "%s", line); +} + +static void print_natlog(log, buf, blen) +FILE *log; +char *buf; +int blen; +{ + struct natlog *nl; + iplog_t *ipl = (iplog_t *)buf; + char *t = line; + struct tm *tm; + int res; + + nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); + res = (opts & OPT_RESOLVE) ? 1 : 0; + tm = localtime((time_t *)&ipl->ipl_sec); + if (!(opts & OPT_SYSLOG)) { + (void) sprintf(t, "%2d/%02d/%4d ", + tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); + t += strlen(t); + } + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld @%hd ", + tm->tm_hour, tm->tm_min, tm->tm_sec, ipl->ipl_usec, + nl->nl_rule+1); + t += strlen(t); + + if (nl->nl_type == NL_NEWMAP) + strcpy(t, "NAT:MAP "); + else if (nl->nl_type == NL_NEWRDR) + strcpy(t, "NAT:RDR "); + else if (nl->nl_type == ISL_EXPIRE) + strcpy(t, "NAT:EXPIRE "); + else + sprintf(t, "Type: %d ", nl->nl_type); + t += strlen(t); + + (void) sprintf(t, "%s,%s <- -> ", hostname(res, nl->nl_inip), + portname(res, NULL, nl->nl_inport)); + t += strlen(t); + (void) sprintf(t, "%s,%s ", hostname(res, nl->nl_outip), + portname(res, NULL, nl->nl_outport)); + t += strlen(t); + (void) sprintf(t, "[%s,%s]", hostname(res, nl->nl_origip), + portname(res, NULL, nl->nl_origport)); + t += strlen(t); + if (nl->nl_type == NL_EXPIRE) { +#ifdef USE_QUAD_T + (void) sprintf(t, " Pkts %qd Bytes %qd", +#else + (void) sprintf(t, " Pkts %ld Bytes %ld", +#endif + nl->nl_pkts, nl->nl_bytes); + t += strlen(t); + } + + *t++ = '\n'; + *t++ = '\0'; + if (opts & OPT_SYSLOG) + syslog(LOG_INFO, "%s", line); + else + (void) fprintf(log, "%s", line); +} + + +static void print_statelog(log, buf, blen) +FILE *log; +char *buf; +int blen; +{ + struct ipslog *sl; + iplog_t *ipl = (iplog_t *)buf; + struct protoent *pr; + char *t = line, *proto, pname[6]; + struct tm *tm; + int res; + + sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); + res = (opts & OPT_RESOLVE) ? 1 : 0; + tm = localtime((time_t *)&ipl->ipl_sec); + if (!(opts & OPT_SYSLOG)) { + (void) sprintf(t, "%2d/%02d/%4d ", + tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); + t += strlen(t); + } + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld ", + tm->tm_hour, tm->tm_min, tm->tm_sec, ipl->ipl_usec); + t += strlen(t); + + if (sl->isl_type == ISL_NEW) + strcpy(t, "STATE:NEW "); + else if (sl->isl_type == ISL_EXPIRE) + strcpy(t, "STATE:EXPIRE "); + else + sprintf(t, "Type: %d ", sl->isl_type); + t += strlen(t); + + pr = getprotobynumber((int)sl->isl_p); + if (!pr) { + proto = pname; + sprintf(proto, "%d", (u_int)sl->isl_p); + } else + proto = pr->p_name; + + if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { + (void) sprintf(t, "%s,%s -> ", + hostname(res, sl->isl_src), + portname(res, proto, sl->isl_sport)); + t += strlen(t); + (void) sprintf(t, "%s,%s PR %s", + hostname(res, sl->isl_dst), + portname(res, proto, sl->isl_dport), proto); + } else if (sl->isl_p == IPPROTO_ICMP) { + (void) sprintf(t, "%s -> ", hostname(res, sl->isl_src)); + t += strlen(t); + (void) sprintf(t, "%s PR icmp %d", + hostname(res, sl->isl_dst), sl->isl_itype); + } + t += strlen(t); + if (sl->isl_type != ISL_NEW) { +#ifdef USE_QUAD_T + (void) sprintf(t, " Pkts %qd Bytes %qd", +#else + (void) sprintf(t, " Pkts %ld Bytes %ld", +#endif + sl->isl_pkts, sl->isl_bytes); + t += strlen(t); + } + + *t++ = '\n'; + *t++ = '\0'; + if (opts & OPT_SYSLOG) + syslog(LOG_INFO, "%s", line); + else + (void) fprintf(log, "%s", line); } -static void printpacket(log, buf, blen) +static void print_log(logtype, log, buf, blen) +FILE *log; +char *buf; +int logtype, blen; +{ + iplog_t *ipl; + int psize; + + while (blen > 0) { + ipl = (iplog_t *)buf; + if (ipl->ipl_magic != IPL_MAGIC) { + /* invalid data or out of sync */ + return; + } + psize = ipl->ipl_dsize; + switch (logtype) + { + case IPL_LOGIPF : + print_ipflog(log, buf, psize); + break; + case IPL_LOGNAT : + print_natlog(log, buf, psize); + break; + case IPL_LOGSTATE : + print_statelog(log, buf, psize); + break; + } + + blen -= psize; + buf += psize; + } +} + + +static void print_ipflog(log, buf, blen) FILE *log; char *buf; int blen; @@ -313,46 +401,54 @@ int blen; struct protoent *pr; struct tcphdr *tp; struct icmp *ic; - struct ip *ipc; struct tm *tm; char c[3], pname[8], *t, *proto; u_short hl, p; - int i, lvl, res; -#if !SOLARIS && !(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603))\ - && !(defined(OpenBSD) && (OpenBSD <= 1991011) && (OpenBSD >= 199603)) - int len; -#endif - struct ip *ip; - struct ipl_ci *lp; - - lp = (struct ipl_ci *)buf; - ip = (struct ip *)(buf + sizeof(*lp)); + int i, lvl, res, len; + ip_t *ipc, *ip; + iplog_t *ipl; + ipflog_t *ipf; + + ipl = (iplog_t *)buf; + ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); + ip = (ip_t *)((char *)ipf + sizeof(*ipf)); res = (opts & OPT_RESOLVE) ? 1 : 0; t = line; *t = '\0'; hl = (ip->ip_hl << 2); p = (u_short)ip->ip_p; - tm = localtime((time_t *)&lp->sec); + tm = localtime((time_t *)&ipl->ipl_sec); +#ifdef linux + ip->ip_len = ntohs(ip->ip_len); +#endif + if (!(opts & OPT_SYSLOG)) { (void) sprintf(t, "%2d/%02d/%4d ", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900); t += strlen(t); } -#if SOLARIS || (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) \ - || (defined(OpenBSD) && (OpenBSD <= 1991011) && (OpenBSD >= 199603)) - (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %.*s @%hd ", - tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec, - (int)sizeof(lp->ifname), lp->ifname, lp->rule); + (void) sprintf(t, "%02d:%02d:%02d.%-.6ld ", tm->tm_hour, tm->tm_min, + tm->tm_sec, ipl->ipl_usec); + t += strlen(t); + if (ipl->ipl_count > 1) { + (void) sprintf(t, "%dx ", ipl->ipl_count); + t += strlen(t); + } +#if (SOLARIS || \ + (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ + (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) + len = (int)sizeof(ipf->fl_ifname); + (void) sprintf(t, "%*.*s", len, len, ipf->fl_ifname); #else for (len = 0; len < 3; len++) - if (!lp->ifname[len]) + if (!ipf->fl_ifname[len]) break; - if (lp->ifname[len]) + if (ipf->fl_ifname[len]) len++; - (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %*.*s%ld @%hd ", - tm->tm_hour, tm->tm_min, tm->tm_sec, lp->usec, - len, len, lp->ifname, lp->unit, lp->rule); + (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); #endif + t += strlen(t); + (void) sprintf(t, " @%hu:%hu ", ipf->fl_group, ipf->fl_rule + 1); pr = getprotobynumber((int)p); if (!pr) { proto = pname; @@ -360,22 +456,22 @@ int blen; } else proto = pr->p_name; - if (lp->flags & (FI_SHORT << 20)) { + if (ipf->fl_flags & FF_SHORT) { c[0] = 'S'; lvl = LOG_ERR; - } else if (lp->flags & FR_PASS) { - if (lp->flags & FR_LOGP) + } else if (ipf->fl_flags & FR_PASS) { + if (ipf->fl_flags & FR_LOGP) c[0] = 'p'; else c[0] = 'P'; lvl = LOG_NOTICE; - } else if (lp->flags & FR_BLOCK) { - if (lp->flags & FR_LOGB) + } else if (ipf->fl_flags & FR_BLOCK) { + if (ipf->fl_flags & FR_LOGB) c[0] = 'b'; else c[0] = 'B'; lvl = LOG_WARNING; - } else if (lp->flags & FF_LOGNOMATCH) { + } else if (ipf->fl_flags & FF_LOGNOMATCH) { c[0] = 'n'; lvl = LOG_NOTICE; } else { @@ -389,7 +485,7 @@ int blen; if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) { tp = (struct tcphdr *)((char *)ip + hl); - if (!(lp->flags & (FI_SHORT << 16))) { + if (!(ipf->fl_flags & (FI_SHORT << 16))) { (void) sprintf(t, "%s,%s -> ", hostname(res, ip->ip_src), portname(res, proto, tp->th_sport)); @@ -426,7 +522,7 @@ int blen; t += strlen(t); (void) sprintf(t, "%s PR icmp len %hu (%hu) icmp %d/%d", hostname(res, ip->ip_dst), hl, - ip->ip_len, ic->icmp_type, ic->icmp_code); + ntohs(ip->ip_len), ic->icmp_type, ic->icmp_code); if (ic->icmp_type == ICMP_UNREACH || ic->icmp_type == ICMP_SOURCEQUENCH || ic->icmp_type == ICMP_PARAMPROB || @@ -467,12 +563,12 @@ int blen; } t += strlen(t); - if (lp->flags & FR_KEEPSTATE) { + if (ipf->fl_flags & FR_KEEPSTATE) { (void) strcpy(t, " K-S"); t += strlen(t); } - if (lp->flags & FR_KEEPFRAG) { + if (ipf->fl_flags & FR_KEEPFRAG) { (void) strcpy(t, " K-F"); t += strlen(t); } @@ -484,50 +580,150 @@ int blen; else (void) fprintf(log, "%s", line); if (opts & OPT_HEXHDR) - dumphex(log, buf, sizeof(struct ipl_ci)); + dumphex(log, (u_char *)buf, sizeof(iplog_t)); if (opts & OPT_HEXBODY) - dumphex(log, ip, lp->plen + lp->hlen); - if (!(opts & OPT_SYSLOG)) - fflush(log); + dumphex(log, (u_char *)ip, ipf->fl_plen + ipf->fl_hlen); +} + + +static void usage(prog) +char *prog; +{ + fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); + exit(1); } + +static void flushlogs(file, log) +char *file; +FILE *log; +{ + int fd, flushed = 0; + + if ((fd = open(file, O_RDWR)) == -1) { + (void) fprintf(stderr, "%s: open: %s\n", file,STRERROR(errno)); + exit(-1); + } + + if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { + printf("%d bytes flushed from log buffer\n", + flushed); + fflush(stdout); + } else + perror("SIOCIPFFB"); + (void) close(fd); + + if (flushed) { + if (opts & OPT_SYSLOG) + syslog(LOG_INFO, "%d bytes flushed from log\n", + flushed); + else if (log != stdout) + fprintf(log, "%d bytes flushed from log\n", flushed); + } +} + + +static void logopts(turnon, options) +int turnon; +char *options; +{ + int flags = 0; + char *s; + + for (s = options; *s; s++) + { + switch (*s) + { + case 'N' : + flags |= OPT_NAT; + break; + case 'S' : + flags |= OPT_STATE; + break; + case 'I' : + flags |= OPT_FILTER; + break; + default : + fprintf(stderr, "Unknown log option %c\n", *s); + exit(1); + } + } + + if (turnon) + opts |= flags; + else + opts &= ~(flags); +} + + int main(argc, argv) int argc; char *argv[]; { - FILE *log = NULL; - int fd = -1, flushed = 0, doread, n; - char buf[512], c, *iplfile = IPL_NAME; + struct stat sb; + FILE *log = stdout; + int fd[3], doread, n, i; + int tr, nr, regular[3], c; + int fdt[3], devices = 0; + char buf[512], *iplfile[3]; extern int optind; extern char *optarg; - while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1) + fd[0] = fd[1] = fd[2] = -1; + fdt[0] = fdt[1] = fdt[2] = -1; + iplfile[0] = IPL_NAME; + iplfile[1] = IPNAT_NAME; + iplfile[2] = IPSTATE_NAME; + + while ((c = getopt(argc, argv, "?af:FhI:nN:o:O:sS:tvxX")) != -1) switch (c) { - case 'f' : - iplfile = optarg; + case 'a' : + opts |= OPT_ALL; + break; + case 'f' : case 'I' : + opts |= OPT_FILTER; + fdt[0] = IPL_LOGIPF; + iplfile[0] = optarg; break; case 'F' : - if ((fd == -1) && - (fd = open(iplfile, O_RDWR)) == -1) { - (void) fprintf(stderr, "%s: ", IPL_NAME); - perror("open"); - exit(-1); - } - if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { - printf("%d bytes flushed from log buffer\n", - flushed); - fflush(stdout); - } else - perror("SIOCIPFFB"); + flushlogs(iplfile[0], log); + flushlogs(iplfile[1], log); + flushlogs(iplfile[2], log); break; - case 'N' : + case 'n' : opts |= OPT_RESOLVE; break; + case 'N' : + opts |= OPT_NAT; + fdt[1] = IPL_LOGNAT; + iplfile[1] = optarg; + break; + case 'o' : case 'O' : + logopts(c == 'o', optarg); + fdt[0] = fdt[1] = fdt[2] = -1; + if (opts & OPT_FILTER) + fdt[0] = IPL_LOGIPF; + if (opts & OPT_NAT) + fdt[1] = IPL_LOGNAT; + if (opts & OPT_STATE) + fdt[2] = IPL_LOGSTATE; + break; + case 'p' : + opts |= OPT_PORTNUM; + break; case 's' : openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC); opts |= OPT_SYSLOG; break; + case 'S' : + opts |= OPT_STATE; + fdt[2] = IPL_LOGSTATE; + iplfile[2] = optarg; + break; + case 't' : + opts |= OPT_TAIL; + break; case 'v' : opts |= OPT_VERBOSE; break; @@ -537,52 +733,106 @@ char *argv[]; case 'X' : opts |= OPT_HEXHDR; break; + default : + case 'h' : + case '?' : + usage(argv[0]); } - if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) { - (void) fprintf(stderr, "%s: ", IPL_NAME); - perror("open"); - exit(-1); + /* + * Default action is to only open the filter log file. + */ + if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) + fdt[0] = IPL_LOGIPF; + + for (i = 0; i < 3; i++) { + if (fdt[i] == -1) + continue; + if (!strcmp(iplfile[i], "-")) + fd[i] = 0; + else { + if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { + (void) fprintf(stderr, + "%s: open: %s\n", iplfile[i], + STRERROR(errno)); + exit(-1); + } + + if (fstat(fd[i], &sb) == -1) { + (void) fprintf(stderr, "%d: fstat: %s\n",fd[i], + STRERROR(errno)); + exit(-1); + } + if (!(regular[i] = !S_ISCHR(sb.st_mode))) + devices++; + } } if (!(opts & OPT_SYSLOG)) { log = argv[optind] ? fopen(argv[optind], "a") : stdout; + if (log == NULL) { + + (void) fprintf(stderr, "%s: fopen: %s\n", argv[optind], + STRERROR(errno)); + exit(-1); + } setvbuf(log, NULL, _IONBF, 0); } else { daemon(0, 0); } - if (flushed) { - if (opts & OPT_SYSLOG) - syslog(LOG_INFO, "%d bytes flushed from log\n", - flushed); - else - fprintf(log, "%d bytes flushed from log\n", flushed); - } + for (doread = 1; doread; ) { + nr = 0; + + for (i = 0; i < 3; i++) { + tr = 0; + if (fdt[i] == -1) + continue; + if (!regular[i]) { + if (ioctl(fd[i], FIONREAD, &tr) == -1) { + perror("ioctl(FIONREAD)"); + exit(-1); + } + } else { + tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); + if (!tr && !(opts & OPT_TAIL)) + doread = 0; + } + if (!tr) + continue; + nr += tr; - for (doread = 1; doread; ) - switch (readlogentry(fd, &n, buf, sizeof(buf), log)) - { - case -1 : - if (opts & OPT_SYSLOG) - syslog(LOG_ERR, "read: %m\n"); - else - perror("read"); - doread = 0; - break; - case 1 : - if (opts & OPT_SYSLOG) - syslog(LOG_ERR, "aborting logging\n"); - else - fprintf(log, "aborting logging\n"); - doread = 0; - break; - case 2 : - break; - case 0 : - printpacket(log, buf, n, opts); - break; + tr = read_log(fd[i], &n, buf, sizeof(buf), log); + switch (tr) + { + case -1 : + if (opts & OPT_SYSLOG) + syslog(LOG_ERR, "read: %m\n"); + else + perror("read"); + doread = 0; + break; + case 1 : + if (opts & OPT_SYSLOG) + syslog(LOG_ERR, "aborting logging\n"); + else + fprintf(log, "aborting logging\n"); + doread = 0; + break; + case 2 : + break; + case 0 : + if (n > 0) { + print_log(fdt[i], log, buf, n); + if (!(opts & OPT_SYSLOG)) + fflush(log); + } + break; + } } + if (!nr && ((opts & OPT_TAIL) || devices)) + sleep(1); + } exit(0); /* NOTREACHED */ } |