summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/ipmon.c
diff options
context:
space:
mode:
authordarrenr <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
committerdarrenr <darrenr@FreeBSD.org>1997-02-09 22:50:16 +0000
commitcb8d46a179f2d30ac1cd0a01eb156e1a4c08d717 (patch)
tree93c7db298b1fd70f9e27663b3fd527da063d0008 /contrib/ipfilter/ipmon.c
downloadFreeBSD-src-cb8d46a179f2d30ac1cd0a01eb156e1a4c08d717.zip
FreeBSD-src-cb8d46a179f2d30ac1cd0a01eb156e1a4c08d717.tar.gz
Import IP Filter v3.1.7 into FreeBSD tree
Diffstat (limited to 'contrib/ipfilter/ipmon.c')
-rw-r--r--contrib/ipfilter/ipmon.c582
1 files changed, 582 insertions, 0 deletions
diff --git a/contrib/ipfilter/ipmon.c b/contrib/ipfilter/ipmon.c
new file mode 100644
index 0000000..2ea34ef
--- /dev/null
+++ b/contrib/ipfilter/ipmon.c
@@ -0,0 +1,582 @@
+/*
+ * (C)opyright 1993-1996 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.
+ */
+
+#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>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <sys/dir.h>
+#include <sys/mbuf.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/user.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.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>
+
+#if !defined(lint) && defined(LIBC_SCCS)
+static char rcsid[] = "$Id: ipmon.c,v 2.0.1.2 1997/02/04 14:49:19 darrenr Exp $";
+#endif
+
+#include "ip_fil.h"
+
+
+struct flags {
+ int value;
+ char flag;
+};
+
+struct flags tcpfl[] = {
+ { TH_ACK, 'A' },
+ { TH_RST, 'R' },
+ { TH_SYN, 'S' },
+ { TH_FIN, 'F' },
+ { TH_URG, 'U' },
+ { TH_PUSH,'P' },
+ { 0, '\0' }
+};
+
+
+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
+
+#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)
+int res;
+struct in_addr ip;
+{
+ struct hostent *hp;
+
+ if (!res)
+ return inet_ntoa(ip);
+ hp = gethostbyaddr((char *)&ip, sizeof(ip), AF_INET);
+ if (!hp)
+ return inet_ntoa(ip);
+ return hp->h_name;
+}
+
+
+char *portname(res, proto, port)
+int res;
+char *proto;
+u_short port;
+{
+ static char pname[8];
+ struct servent *serv;
+
+ (void) sprintf(pname, "%hu", htons(port));
+ if (!res)
+ return pname;
+ serv = getservbyport((int)port, proto);
+ if (!serv)
+ return pname;
+ return serv->s_name;
+}
+
+
+static void dumphex(log, buf, len)
+FILE *log;
+u_char *buf;
+int len;
+{
+ char line[80];
+ int i, j, k;
+ u_char *s = buf, *t = (u_char *)line;
+
+ 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 -= 15;
+ sprintf(t, " ");
+ t += 8;
+ for (k = 16; k; k--, s++)
+ *t++ = (isprint(*s) ? *s : '.');
+ s--;
+ }
+
+ if ((j + 1) & 0xf)
+ *t++ = ' ';;
+ }
+
+ 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, buf, blen)
+FILE *log;
+char *buf;
+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))
+ int len;
+#endif
+ struct ip *ip;
+ struct ipl_ci *lp;
+
+ 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 & 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))
+ (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);
+#else
+ for (len = 0; len < 3; len++)
+ if (!lp->ifname[len])
+ break;
+ if (lp->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);
+#endif
+ pr = getprotobynumber((int)p);
+ if (!pr) {
+ proto = pname;
+ sprintf(proto, "%d", (u_int)p);
+ } else
+ proto = pr->p_name;
+
+ if (lp->flags & (FI_SHORT << 20)) {
+ c[0] = 'S';
+ lvl = LOG_ERR;
+ } else if (lp->flags & FR_PASS) {
+ if (lp->flags & FR_LOGP)
+ c[0] = 'p';
+ else
+ c[0] = 'P';
+ lvl = LOG_NOTICE;
+ } else if (lp->flags & FR_BLOCK) {
+ if (lp->flags & FR_LOGB)
+ c[0] = 'b';
+ else
+ c[0] = 'B';
+ lvl = LOG_WARNING;
+ } else if (lp->flags & FF_LOGNOMATCH) {
+ c[0] = 'n';
+ lvl = LOG_NOTICE;
+ } else {
+ c[0] = 'L';
+ lvl = LOG_INFO;
+ }
+ c[1] = ' ';
+ c[2] = '\0';
+ (void) strcat(line, c);
+ t = line + strlen(line);
+
+ if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !(ip->ip_off & 0x1fff)) {
+ tp = (struct tcphdr *)((char *)ip + hl);
+ if (!(lp->flags & (FI_SHORT << 16))) {
+ (void) sprintf(t, "%s,%s -> ",
+ hostname(res, ip->ip_src),
+ portname(res, proto, tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, "%s,%s PR %s len %hu %hu ",
+ hostname(res, ip->ip_dst),
+ portname(res, proto, tp->th_dport),
+ proto, hl, ip->ip_len);
+ t += strlen(t);
+
+ if (p == IPPROTO_TCP) {
+ *t++ = '-';
+ for (i = 0; tcpfl[i].value; i++)
+ 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));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu %hu",
+ hostname(res, ip->ip_dst), proto,
+ hl, ip->ip_len);
+ }
+ } else if (p == IPPROTO_ICMP) {
+ ic = (struct icmp *)((char *)ip + hl);
+ (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
+ 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);
+ if (ic->icmp_type == ICMP_UNREACH ||
+ ic->icmp_type == ICMP_SOURCEQUENCH ||
+ ic->icmp_type == ICMP_PARAMPROB ||
+ ic->icmp_type == ICMP_REDIRECT ||
+ ic->icmp_type == ICMP_TIMXCEED) {
+ ipc = &ic->icmp_ip;
+ tp = (struct tcphdr *)((char *)ipc + hl);
+
+ p = (u_short)ipc->ip_p;
+ pr = getprotobynumber((int)p);
+ if (!pr) {
+ proto = pname;
+ (void) sprintf(proto, "%d", (int)p);
+ } else
+ proto = pr->p_name;
+
+ t += strlen(t);
+ (void) sprintf(t, " for %s,%s -",
+ hostname(res, ipc->ip_src),
+ portname(res, proto, tp->th_sport));
+ t += strlen(t);
+ (void) sprintf(t, " %s,%s PR %s len %hu %hu",
+ hostname(res, ipc->ip_dst),
+ portname(res, proto, tp->th_dport),
+ proto, ipc->ip_hl << 2, ipc->ip_len);
+ }
+ } else {
+ (void) sprintf(t, "%s -> ", hostname(res, ip->ip_src));
+ t += strlen(t);
+ (void) sprintf(t, "%s PR %s len %hu (%hu)",
+ hostname(res, ip->ip_dst), proto, hl, ip->ip_len);
+ t += strlen(t);
+ if (ip->ip_off & 0x1fff)
+ (void) sprintf(t, " frag %s%s%hu@%hu",
+ ip->ip_off & IP_MF ? "+" : "",
+ ip->ip_off & IP_DF ? "-" : "",
+ ip->ip_len - hl, (ip->ip_off & 0x1fff) << 3);
+ }
+ t += strlen(t);
+
+ if (lp->flags & FR_KEEPSTATE) {
+ (void) strcpy(t, " K-S");
+ t += strlen(t);
+ }
+
+ if (lp->flags & FR_KEEPFRAG) {
+ (void) strcpy(t, " K-F");
+ t += strlen(t);
+ }
+
+ *t++ = '\n';
+ *t++ = '\0';
+ 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);
+}
+
+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;
+ extern int optind;
+ extern char *optarg;
+
+ 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 |= OPT_RESOLVE;
+ break;
+ case 's' :
+ openlog(argv[0], LOG_NDELAY|LOG_PID, LOGFAC);
+ opts |= OPT_SYSLOG;
+ break;
+ case 'v' :
+ opts |= OPT_VERBOSE;
+ break;
+ case 'x' :
+ opts |= OPT_HEXBODY;
+ break;
+ case 'X' :
+ opts |= OPT_HEXHDR;
+ break;
+ }
+
+ 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);
+ }
+
+ 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 */
+}
OpenPOWER on IntegriCloud