ipmon.c revision 049fa28a1fa444b1ffffe4e619e7e39fbd617462
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef SOLARIS
#endif
#define _KERNEL
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
# if (__FreeBSD_version >= 300000)
# else
# endif
#else
# include <sys/byteorder.h>
#endif
# include <strings.h>
#endif
#include <signal.h>
#include <stdlib.h>
#include <stddef.h>
#include <netinet/in_systm.h>
#if !defined(__hpux)
#endif
#include <netdb.h>
#ifdef __hpux
#endif
#include <resolv.h>
#include <ctype.h>
#include <syslog.h>
#if SOLARIS2 >= 10
#include "ip_compat.h"
#include "ip_fil.h"
#include "ip_nat.h"
#include "ip_state.h"
#include "ip_proxy.h"
#else
#include "netinet/ip_compat.h"
#include "netinet/ip_state.h"
#include "netinet/ip_proxy.h"
#endif
#include "ipmon.h"
#if !defined(lint)
#endif
#define STRERROR(x) sys_errlist[x]
extern char *sys_errlist[];
#else
#endif
struct flags {
int value;
char flag;
};
typedef struct icmp_subtype {
int ist_val;
char *ist_name;
typedef struct icmp_type {
int it_val;
struct icmp_subtype *it_subtable;
char *it_name;
} icmp_type_t;
#define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
{ TH_ACK, 'A' },
{ TH_RST, 'R' },
{ TH_SYN, 'S' },
{ TH_FIN, 'F' },
{ TH_URG, 'U' },
{ TH_PUSH,'P' },
{ TH_ECN, 'E' },
{ TH_CWR, 'C' },
{ 0, '\0' }
};
#else
# else
# endif
#endif
static char line[2048];
static int opts = 0;
static char *binarylogfile = NULL;
static int donehup = 0;
#ifdef __hpux
#else
#endif
#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_LOGBODY 0x800
#ifndef LOGFAC
#define LOGFAC LOG_LOCAL0
#endif
static icmp_subtype_t icmpunreachnames[] = {
{ ICMP_UNREACH_NET, "net" },
{ ICMP_UNREACH_HOST, "host" },
{ ICMP_UNREACH_PROTOCOL, "protocol" },
{ ICMP_UNREACH_PORT, "port" },
{ ICMP_UNREACH_NEEDFRAG, "needfrag" },
{ ICMP_UNREACH_SRCFAIL, "srcfail" },
{ ICMP_UNREACH_NET_UNKNOWN, "net_unknown" },
{ ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" },
{ ICMP_UNREACH_NET, "isolated" },
{ ICMP_UNREACH_NET_PROHIB, "net_prohib" },
{ ICMP_UNREACH_NET_PROHIB, "host_prohib" },
{ ICMP_UNREACH_TOSNET, "tosnet" },
{ ICMP_UNREACH_TOSHOST, "toshost" },
{ ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" },
{ -2, NULL }
};
static icmp_subtype_t redirectnames[] = {
{ ICMP_REDIRECT_NET, "net" },
{ ICMP_REDIRECT_HOST, "host" },
{ ICMP_REDIRECT_TOSNET, "tosnet" },
{ ICMP_REDIRECT_TOSHOST, "toshost" },
{ -2, NULL }
};
static icmp_subtype_t timxceednames[] = {
{ ICMP_TIMXCEED_INTRANS, "transit" },
{ ICMP_TIMXCEED_REASS, "reassem" },
{ -2, NULL }
};
static icmp_subtype_t paramnames[] = {
{ ICMP_PARAMPROB_ERRATPTR, "errata_pointer" },
{ ICMP_PARAMPROB_OPTABSENT, "optmissing" },
{ ICMP_PARAMPROB_LENGTH, "length" },
{ -2, NULL }
};
static icmp_type_t icmptypes[] = {
};
static icmp_subtype_t icmpredirect6[] = {
{ ICMP6_DST_UNREACH_NOROUTE, "noroute" },
{ ICMP6_DST_UNREACH_ADMIN, "admin" },
{ ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" },
{ ICMP6_DST_UNREACH_ADDR, "address" },
{ ICMP6_DST_UNREACH_NOPORT, "noport" },
{ -2, NULL }
};
static icmp_subtype_t icmptimexceed6[] = {
{ ICMP6_TIME_EXCEED_TRANSIT, "intransit" },
{ ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" },
{ -2, NULL }
};
static icmp_subtype_t icmpparamprob6[] = {
{ ICMP6_PARAMPROB_HEADER, "header" },
{ ICMP6_PARAMPROB_NEXTHEADER, "nextheader" },
{ ICMP6_PARAMPROB_OPTION, "option" },
{ -2, NULL }
};
static icmp_subtype_t icmpquerysubject6[] = {
{ ICMP6_NI_SUBJ_IPV6, "ipv6" },
{ ICMP6_NI_SUBJ_FQDN, "fqdn" },
{ ICMP6_NI_SUBJ_IPV4, "ipv4" },
{ -2, NULL },
};
static icmp_subtype_t icmpnodeinfo6[] = {
{ ICMP6_NI_SUCCESS, "success" },
{ ICMP6_NI_REFUSED, "refused" },
{ ICMP6_NI_UNKNOWN, "unknown" },
{ -2, NULL }
};
static icmp_subtype_t icmprenumber6[] = {
{ ICMP6_ROUTER_RENUMBERING_COMMAND, "command" },
{ ICMP6_ROUTER_RENUMBERING_RESULT, "result" },
{ ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" },
{ -2, NULL }
};
static icmp_type_t icmptypes6[] = {
};
int type;
{
int i;
if (tablesz < 2)
return NULL;
return NULL;
i = type;
return ist;
return NULL;
}
int type;
{
int i;
if (tablesz < 2)
return NULL;
return NULL;
i = type;
return it;
return NULL;
}
int sig;
{
newbinarylog = fp;
init_tabs();
if (conf_file)
exit(1);
donehup = 1;
}
static void init_tabs()
{
struct protoent *p;
struct servent *s;
int port, i;
for (i = 0; i < 256; i++)
}
}
setprotoent(1);
while ((p = getprotoent()) != NULL)
endprotoent();
}
for (i = 0; i < 65536; i++)
}
}
for (i = 0; i < 65536; i++)
}
}
setservent(1);
while ((s = getservent()) != NULL) {
continue;
} else
continue;
continue;
}
endservent();
}
static char *getproto(p)
u_int p;
{
static char pnum[4];
char *s;
p &= 0xff;
if (s == NULL) {
s = pnum;
}
return s;
}
char *buf;
{
int nr;
if (!nr)
return 2;
return -1;
return 0;
}
int res, v;
{
# define MAX_INETA 16
#ifdef USE_INET6
#endif
if (v == 4) {
if (!res)
if (!hp)
return hname;
}
#ifdef USE_INET6
return hostbuf;
#else
return "IPv6";
#endif
}
int res;
char *proto;
{
static char pname[8];
char *s;
port &= 0xffff;
return pname;
s = NULL;
if (s == NULL)
s = pname;
return s;
}
{
static char name[80];
char *s;
s = NULL;
if (s == NULL)
else
else
return name;
}
{
static char name[80];
char *s;
s = NULL;
if (s == NULL)
else
else
return name;
}
int dopts;
char *buf;
int len;
{
char hline[80];
int i, j, k;
return;
*hline = '\0';
for (i = len, j = 0; i; i--, j++, s++) {
if (j && !(j & 0xf)) {
*t++ = '\n';
*t = '\0';
if (!(dopts & OPT_SYSLOG))
else
*t = '\0';
}
t += 2;
if (!((j + 1) & 0xf)) {
s -= 15;
sprintf((char *)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((char *)t, " ");
t += 7;
s -= j & 0xf;
for (k = j & 0xf; k; k--, s++)
*t++ = (isprint(*s) ? *s : '.');
*t++ = '\n';
*t = '\0';
}
if (!(dopts & OPT_SYSLOG)) {
} else
}
#ifdef __hpux
#else
#endif
{
time_t t;
t = sec;
return tm;
}
char *buf;
int blen;
{
char *t = line;
char *proto;
if (!(opts & OPT_SYSLOG)) {
i = strlen(t);
len -= i;
t += i;
}
t += strlen(t);
t += strlen(t);
strcpy(t, "NAT:MAP ");
strcpy(t, "NAT:RDR ");
strcpy(t, "NAT:FLUSH ");
strcpy(t, "NAT:EXPIRE ");
strcpy(t, "NAT:BIMAP ");
strcpy(t, "NAT:MAPBLOCK ");
strcpy(t, "NAT:CLONE ");
else
t += strlen(t);
t += strlen(t);
t += strlen(t);
t += strlen(t);
#ifdef USE_QUAD_T
(void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd",
#else
(void) sprintf(t, " Pkts %ld Bytes %ld",
#endif
t += strlen(t);
}
*t++ = '\n';
*t++ = '\0';
if (opts & OPT_SYSLOG)
else
}
char *buf;
int blen;
{
if (!(opts & OPT_SYSLOG)) {
i = strlen(t);
len -= i;
t += i;
}
t += strlen(t);
t += strlen(t);
strcpy(t, "STATE:NEW ");
strcpy(t, "STATE:CLONED ");
strcpy(t, "STATE:CLOSE ");
else
strcpy(t, "STATE:EXPIRE ");
strcpy(t, "STATE:FLUSH ");
strcpy(t, "STATE:INTERMEDIATE ");
strcpy(t, "STATE:REMOVE ");
strcpy(t, "STATE:KILLED ");
else
t += strlen(t);
(void) sprintf(t, "%s,%s -> ",
t += strlen(t);
(void) sprintf(t, "%s,%s PR %s",
t += strlen(t);
(void) sprintf(t, "%s PR icmp %d",
t += strlen(t);
(void) sprintf(t, "%s PR icmpv6 %d",
}
t += strlen(t);
t += strlen(t);
}
sprintf(t,
#ifdef USE_QUAD_T
" 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",
#else
" 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",
#endif
t += strlen(t);
}
*t++ = '\n';
*t++ = '\0';
if (opts & OPT_SYSLOG)
else
}
char *buf;
{
int psize;
while (blen > 0) {
if (bp)
perror("malloc");
exit(1);
}
if (bpo) {
}
continue;
}
break;
if (binarylog) {
}
if (logtype == IPL_LOGIPF) {
/* invalid data or out of sync */
break;
}
} else if (logtype == IPL_LOGNAT) {
/* invalid data or out of sync */
break;
}
} else if (logtype == IPL_LOGSTATE) {
/* invalid data or out of sync */
break;
}
}
}
if (bp)
return;
}
char *buf;
int blen;
{
char *t, *proto;
#ifdef USE_INET6
#endif
t = line;
*t = '\0';
if (!(opts & OPT_SYSLOG)) {
i = strlen(t);
len -= i;
t += i;
}
t += strlen(t);
t += strlen(t);
t += strlen(t);
}
#if (defined(MENTAT) || \
{
t += strlen(t);
# if defined(MENTAT)
if (isalpha(*(t - 1))) {
t += strlen(t);
}
# endif
}
#else
break;
len++;
t += strlen(t);
#endif
strcat(t, " @-1:");
(void) strcpy(t, " @0:");
else
t += strlen(t);
strcat(t, "-1 ");
else
t += strlen(t);
lvl = LOG_NOTICE;
*t++ = 'S';
}
*t++ = 'p';
else
*t++ = 'P';
*t++ = 'b';
else
*t++ = 'B';
lvl = LOG_WARNING;
*t++ = 'L';
*t++ = 'n';
} else {
*t++ = '?';
}
*t++ = ' ';
*t = '\0';
if (v == 6) {
#ifdef USE_INET6
off = 0;
ipoff = 0;
#else
sprintf(t, "ipv6");
goto printipflog;
#endif
} else if (v == 4) {
} else {
goto printipflog;
}
t += strlen(t);
(void) sprintf(t, "%s,%s PR %s len %hu %hu",
t += strlen(t);
if (p == IPPROTO_TCP) {
*t++ = ' ';
*t++ = '-';
if (opts & OPT_VERBOSE) {
(void) sprintf(t, " %lu %lu %hu",
t += strlen(t);
}
}
*t = '\0';
} else {
t += strlen(t);
(void) sprintf(t, "%s PR %s len %hu %hu",
}
t += strlen(t);
(void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s",
t += strlen(t);
(void) sprintf(t, "%s PR icmp len %hu %hu icmp %s",
/*
* XXX - try to guess endian of ip_len in ICMP
* returned data.
*/
if (i > 1500)
if (!(ipoff & IP_OFFMASK) &&
t += strlen(t);
(void) sprintf(t, " for %s,%s -",
t += strlen(t);
(void) sprintf(t, " %s,%s PR %s len %hu %hu",
} else if (!(ipoff & IP_OFFMASK) &&
t += strlen(t);
(void) sprintf(t, " for %s -",
t += strlen(t);
(void) sprintf(t,
" %s PR icmp len %hu %hu icmp %d/%d",
} else {
t += strlen(t);
(void) sprintf(t, " for %s -",
t += strlen(t);
(void) sprintf(t, " %s PR %s len %hu (%hu)",
t += strlen(t);
if (ipoff & IP_OFFMASK) {
(void) sprintf(t, " frag %s%s%hu@%hu",
}
}
}
} else {
t += strlen(t);
(void) sprintf(t, "%s PR %s len %hu (%hu)",
t += strlen(t);
if (off & IP_OFFMASK)
(void) sprintf(t, " frag %s%s%hu@%hu",
}
t += strlen(t);
(void) strcpy(t, " K-S");
t += strlen(t);
}
(void) strcpy(t, " K-F");
t += strlen(t);
}
strcpy(t, " IN");
strcpy(t, " OUT");
t += strlen(t);
t += strlen(t);
}
*t++ = '\n';
*t++ = '\0';
if (opts & OPT_SYSLOG)
else
if (opts & OPT_HEXHDR)
if (opts & OPT_HEXBODY)
if (conf_file)
}
char *prog;
{
"[-P pidfile]", "[-S device]", "[-f device]",
"filename");
exit(1);
}
char *file;
{
int fd;
return;
}
}
}
char *file;
{
exit(1);
}
printf("%d bytes flushed from log buffer\n",
flushed);
} else
perror("SIOCIPFFB");
if (flushed) {
if (opts & OPT_SYSLOG)
flushed);
}
}
int turnon;
char *options;
{
int flags = 0;
char *s;
for (s = options; *s; s++)
{
switch (*s)
{
case 'N' :
break;
case 'S' :
break;
case 'I' :
flags |= OPT_FILTER;
break;
default :
exit(1);
}
}
if (turnon)
else
}
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
switch (c)
{
case 'a' :
opts |= OPT_LOGALL;
fdt[0] = IPL_LOGIPF;
break;
case 'b' :
opts |= OPT_LOGBODY;
break;
case 'B' :
break;
case 'C' :
break;
case 'D' :
make_daemon = 1;
break;
case 'f' : case 'I' :
opts |= OPT_FILTER;
fdt[0] = IPL_LOGIPF;
break;
case 'F' :
break;
case 'n' :
opts |= OPT_RESOLVE;
break;
case 'N' :
break;
case 'o' : case 'O' :
if (opts & OPT_FILTER)
fdt[0] = IPL_LOGIPF;
break;
case 'p' :
opts |= OPT_PORTNUM;
break;
case 'P' :
break;
case 's' :
if (s == NULL)
s = argv[0];
else
s++;
s = NULL;
opts |= OPT_SYSLOG;
break;
case 'S' :
break;
case 't' :
break;
case 'v' :
opts |= OPT_VERBOSE;
break;
case 'x' :
opts |= OPT_HEXBODY;
break;
case 'X' :
opts |= OPT_HEXHDR;
break;
default :
case 'h' :
case '?' :
}
init_tabs();
if (conf_file)
exit(1);
/*
* Default action is to only open the filter log file.
*/
fdt[0] = IPL_LOGIPF;
for (i = 0; i < 3; i++) {
if (fdt[i] == -1)
continue;
fd[i] = 0;
else {
"%s: open: %s\n", iplfile[i],
exit(1);
/* NOTREACHED */
}
exit(1);
/* NOTREACHED */
}
devices++;
}
}
if (!(opts & OPT_SYSLOG)) {
exit(1);
/* NOTREACHED */
}
} else
#if BSD >= 199306
#else
int pid;
exit(0);
if (pid < 0) {
exit(1);
/* NOTREACHED */
}
setsid();
if ((opts & OPT_SYSLOG))
close(2);
#endif /* !BSD */
close(0);
close(1);
}
nr = 0;
for (i = 0; i < 3; i++) {
tr = 0;
if (fdt[i] == -1)
continue;
if (!regular[i]) {
if (opts & OPT_SYSLOG)
"ioctl(FIONREAD): %m");
else
perror("ioctl(FIONREAD)");
exit(1);
/* NOTREACHED */
}
} else {
doread = 0;
}
if (!tr)
continue;
if (donehup) {
donehup = 0;
if (newlog) {
}
if (newbinarylog) {
newbinarylog = NULL;
}
}
switch (tr)
{
case -1 :
if (opts & OPT_SYSLOG)
else
perror("read");
doread = 0;
break;
case 1 :
if (opts & OPT_SYSLOG)
else
doread = 0;
break;
case 2 :
break;
case 0 :
if (n > 0) {
if (!(opts & OPT_SYSLOG))
}
break;
}
}
sleep(1);
}
return(0);
/* NOTREACHED */
}