diff options
Diffstat (limited to 'usr.sbin/ipmon/ipmon.c')
-rw-r--r-- | usr.sbin/ipmon/ipmon.c | 361 |
1 files changed, 295 insertions, 66 deletions
diff --git a/usr.sbin/ipmon/ipmon.c b/usr.sbin/ipmon/ipmon.c index ba827cec129..e7a488b4bf9 100644 --- a/usr.sbin/ipmon/ipmon.c +++ b/usr.sbin/ipmon/ipmon.c @@ -11,7 +11,8 @@ #include <unistd.h> #include <fcntl.h> #include <string.h> -#include <sys/syslog.h> +#include <stdlib.h> +#include <syslog.h> #include <sys/errno.h> #include <sys/file.h> #include <sys/ioctl.h> @@ -37,15 +38,16 @@ #include <netinet/ip_icmp.h> #include <netdb.h> #include <arpa/inet.h> +#include <ctype.h> -#ifndef lint -static char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-1996 Darren Reed"; -static char rcsid[] = "$Id: ipmon.c,v 1.6 1996/10/08 07:33:38 niklas Exp $"; +#if !defined(lint) && defined(LIBC_SCCS) +static char rcsid[] = "$Id: ipmon.c,v 1.7 1997/02/11 22:24:10 kstailey Exp $"; #endif #include "ip_fil_compat.h" #include "ip_fil.h" + struct flags { int value; char flag; @@ -61,8 +63,162 @@ struct flags tcpfl[] = { { 0, '\0' } }; + static char line[2048]; -static void printpacket(); +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 + +#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) +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; + return 0; +} char *hostname(res, ip) @@ -98,39 +254,61 @@ u_short port; } -static void dumphex(log, ip, lp) +static void dumphex(log, buf, len) FILE *log; -struct ip *ip; -struct ipl_ci *lp; +u_char *buf; +int len; { + char line[80]; int i, j, k; - u_char *s = (u_char *)ip; + u_char *s = buf, *t = (u_char *)line; - for (i = lp->plen + lp->hlen, j = 0; i; i--, j++, s++) { - if (j && !(j & 0xf)) - putchar('\n'); - printf("%02x", *s); + for (i = len, j = 0; i; i--, j++, s++) { + if (j && !(j & 0xf)) { + *t++ = '\n'; + *t = '\0'; + fputs(line, stdout); + t = (u_char *)line; + *t = '\0'; + } + sprintf(t, "%02x", *s & 0xff); + t += 2; if (!((j + 1) & 0xf)) { - s -= 16; - printf(" "); + s -= 15; + sprintf(t, " "); + t += 8; for (k = 16; k; k--, s++) - putchar(isprint(*s) ? *s : '.'); + *t++ = (isprint(*s) ? *s : '.'); + s--; } if ((j + 1) & 0xf) - putchar(' '); + *t++ = ' ';; } - if ((j - 1) & 0xf) - putchar('\n'); + if (j & 0xf) { + for (k = 16 - (j & 0xf); k; k--) { + *t++ = ' '; + *t++ = ' '; + *t++ = ' '; + } + sprintf(t, " "); + t += 7; + s -= j & 0xf; + for (k = j & 0xf; k; k--, s++) + *t++ = (isprint(*s) ? *s : '.'); + *t++ = '\n'; + *t = '\0'; + } + fputs(line, stdout); + fflush(stdout); } -static void printpacket(log, ip, lp, opts) +static void printpacket(log, buf, blen) FILE *log; -struct ip *ip; -struct ipl_ci *lp; -int opts; +char *buf; +int blen; { struct protoent *pr; struct tcphdr *tp; @@ -139,24 +317,32 @@ int opts; struct tm *tm; char c[3], pname[8], *t, *proto; u_short hl, p; - int i, lvl, res, len; + 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; - res = (opts & 2) ? 1 : 0; + lp = (struct ipl_ci *)buf; + ip = (struct ip *)(buf + sizeof(*lp)); + 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); - if (!(opts & 1)) { + 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 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ - (defined(OpenBSD) && (OpenBSD >= 199606)) - (void) sprintf(t, "%02d:%02d:%02d.%-.6ld %s @%hd ", +#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, - lp->ifname, lp->rule); + (int)sizeof(lp->ifname), lp->ifname, lp->rule); #else for (len = 0; len < 3; len++) if (!lp->ifname[len]) @@ -220,6 +406,12 @@ int opts; if (tp->th_flags & tcpfl[i].value) *t++ = tcpfl[i].flag; } + if (opts & OPT_VERBOSE) { + (void) sprintf(t, " %lu %lu %hu", + (u_long)tp->th_seq, + (u_long)tp->th_ack, tp->th_win); + t += strlen(t); + } *t = '\0'; } else { (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src)); @@ -287,70 +479,107 @@ int opts; *t++ = '\n'; *t++ = '\0'; - if (opts & 1) + if (opts & OPT_SYSLOG) syslog(lvl, "%s", line); else (void) fprintf(log, "%s", line); + if (opts & OPT_HEXHDR) + dumphex(log, buf, sizeof(struct ipl_ci)); + if (opts & OPT_HEXBODY) + dumphex(log, ip, lp->plen + lp->hlen); fflush(log); - if (opts & 4) - dumphex(log, ip, lp); } int main(argc, argv) int argc; char *argv[]; { - FILE *log; - int fd, flushed = 0, opts = 0; - u_int len; - char buf[512], c; - struct ipl_ci iplci; + FILE *log = NULL; + int fd = -1, flushed = 0, doread, n; + char buf[512], c, *iplfile = IPL_NAME; extern int optind; + extern char *optarg; - if ((fd = open(IPL_NAME, O_RDONLY)) == -1) { - (void) fprintf(stderr, "%s: ", IPL_NAME); - perror("open"); - exit(-1); - } - - while ((c = getopt(argc, argv, "Nfsx")) != -1) + while ((c = getopt(argc, argv, "Nf:FsvxX")) != -1) switch (c) { case 'f' : + iplfile = 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"); break; case 'N' : - opts |= 2; - break; - case 'x' : - opts |= 4; + opts |= OPT_RESOLVE; break; case 's' : openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC); - opts |= 1; + opts |= OPT_SYSLOG; + break; + case 'v' : + opts |= OPT_VERBOSE; + break; + case 'x' : + opts |= OPT_HEXBODY; + break; + case 'X' : + opts |= OPT_HEXHDR; break; } - log = argv[optind] ? fopen(argv[1], "a") : stdout; - setvbuf(log, NULL, _IONBF, 0); - if (flushed) - fprintf(log, "%d bytes flushed from log\n", flushed); - - while (1) { - assert(read(fd, &iplci, sizeof(struct ipl_ci)) == - sizeof(struct ipl_ci)); - assert(iplci.hlen > 0 && iplci.hlen <= 92); - len = (u_int)iplci.plen; - assert(len <= 128); - assert(read(fd, buf, iplci.hlen + iplci.plen) == - (iplci.hlen + iplci.plen)); - printpacket(log, buf, &iplci, opts); + if ((fd == -1) && (fd = open(iplfile, O_RDONLY)) == -1) { + (void) fprintf(stderr, "%s: ", IPL_NAME); + perror("open"); + exit(-1); + } + + if (!(opts & OPT_SYSLOG)) { + log = argv[optind] ? fopen(argv[optind], "a") : stdout; + setvbuf(log, NULL, _IONBF, 0); } - /* NOTREACHED */ + + 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; ) + 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; + } exit(0); /* NOTREACHED */ } |