Subject: Re: Problem with ipmon(8)
To: Matthias Scheler <tron@zhadum.de>
From: Greg A. Woods <woods@weird.com>
List: tech-net
Date: 07/04/2001 17:36:35
[ On Wednesday, July 4, 2001 at 21:46:22 (+0200), Manuel Bouyer wrote: ]
> Subject: Re: Problem with ipmon(8)
>
> On Tue, Jul 03, 2001 at 09:01:19PM +0000, Matthias Scheler wrote:
> > Hello,
> >
> > I start "ipmon" with the default flags "-sn" at system startup time to
> > watch the packet filter on my NetBSD NAT gateway. After a few hours
> > "ipmon" simply dies. Does anybody else these this problem?
>
> which NetBSD version ? On 1.5 I've never seen this.
> Does it dump core ?
He's not using '-D', which means if he hits ^C on the console then ipmon
will die. Matthias you have to use '-D' when starting ipmon. It should
be the default, but it's not (perhaps because it was designed initially
to run under a SysV-style init with /etc/inittab).
I meant to follow up on this thread too....
Long long ago I fixed my copy of ipmon.c to call daemon(0,0) instead of
trying to do its own variant.
I also fixed it so that it wouldn't close stderr so as to facilitate the
times when it tries to write to STDERR if OPT_SYSLOG is set (so that I
could see any errors that it did complain about!).
You'll find these fixes among the attached diffs.... (which also
include other fixes and a little gift: ICMP code->ASCII translation :-)
I seem to remember that before I made these changes ipmon would
occasionally die on me too, even with -D.
--
Greg A. Woods
+1 416 218-0098 VE3TCP <gwoods@acm.org> <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; Secrets of the Weird <woods@weird.com>
Index: ipmon.c
===================================================================
RCS file: /cvs/NetBSD/src/dist/ipf/ipmon.c,v
retrieving revision 1.1.1.4
diff -c -c -r1.1.1.4 ipmon.c
*** ipmon.c 2001/06/12 21:03:00 1.1.1.4
--- ipmon.c 2001/07/04 21:28:11
***************
*** 123,128 ****
--- 123,129 ----
static void dumphex __P((FILE *, u_char *, int));
static int read_log __P((int, int *, char *, int));
static void write_pid __P((char *));
+ static char *icmpname __P((u_int, u_int));
char *hostname __P((int, int, u_32_t *));
char *portname __P((int, char *, u_int));
***************
*** 135,142 ****
static char **protocols = NULL;
static char **udp_ports = NULL;
static char **tcp_ports = NULL;
-
#define OPT_SYSLOG 0x001
#define OPT_RESOLVE 0x002
#define OPT_HEXBODY 0x004
--- 136,143 ----
static char **protocols = NULL;
static char **udp_ports = NULL;
static char **tcp_ports = NULL;
+ static char *argv0 = "ipmon";
#define OPT_SYSLOG 0x001
#define OPT_RESOLVE 0x002
#define OPT_HEXBODY 0x004
***************
*** 267,272 ****
--- 268,275 ----
int res, v;
u_32_t *ip;
{
+ # define MAX_INETA 16
+ static char hname[MAXHOSTNAMELEN + MAX_INETA + 3];
#ifdef USE_INET6
static char hostbuf[MAXHOSTNAMELEN+1];
#endif
***************
*** 280,287 ****
hp = gethostbyaddr((char *)ip, sizeof(ip), AF_INET);
if (!hp)
return inet_ntoa(ipa);
! return hp->h_name;
!
}
#ifdef USE_INET6
(void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1);
--- 283,290 ----
hp = gethostbyaddr((char *)ip, sizeof(ip), AF_INET);
if (!hp)
return inet_ntoa(ipa);
! sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, inet_ntoa(ipa));
! return hname;
}
#ifdef USE_INET6
(void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1);
***************
*** 317,322 ****
--- 320,449 ----
}
+ char *icmpname(type, code)
+ u_int type;
+ u_int code;
+ {
+ static char name[80]; /* > sizeof("UNREACH_ADMIN_PROHIBIT/NNNN") */
+ char codeval[8]; /* > sizeof("/NN") */
+
+ if (code)
+ sprintf(codeval, "/%d", code);
+ else
+ codeval[0] = '\0';
+ switch (type) {
+ case ICMP_ECHOREPLY: /* 0 */
+ sprintf(name, "echoreply%s", codeval);
+ break;
+ case ICMP_UNREACH: /* 3 */
+ switch (code) {
+ case ICMP_UNREACH_NET: /* 0 */
+ return("unreach/net");
+ case ICMP_UNREACH_HOST: /* 1 */
+ return("unreach/host");
+ case ICMP_UNREACH_PROTOCOL: /* 2 */
+ return("unreach/protocol");
+ case ICMP_UNREACH_PORT: /* 3 */
+ return("unreach/port");
+ case ICMP_UNREACH_NEEDFRAG: /* 4 */
+ return("unreach/needfrag");
+ case ICMP_UNREACH_SRCFAIL: /* 5 */
+ return("unreach/srcfail");
+ case ICMP_UNREACH_NET_UNKNOWN: /* 6 */
+ return("unreach/net_unknown");
+ case ICMP_UNREACH_HOST_UNKNOWN: /* 7 */
+ return("unreach/host_unknown");
+ case ICMP_UNREACH_ISOLATED: /* 8 */
+ return("unreach/isolated");
+ case ICMP_UNREACH_NET_PROHIB: /* 9 */
+ return("unreach/net_prohib");
+ case ICMP_UNREACH_HOST_PROHIB: /* 10 */
+ return("unreach/host_prohib");
+ case ICMP_UNREACH_TOSNET: /* 11 */
+ return("unreach/tosnet");
+ case ICMP_UNREACH_TOSHOST: /* 12 */
+ return("unreach/toshost");
+ case ICMP_UNREACH_ADMIN_PROHIBIT: /* 13 */
+ return("unreach/admin_prohibit");
+ default:
+ sprintf(name, "unreach/%d", code);
+ break;
+ }
+ break;
+ case ICMP_SOURCEQUENCH: /* 4 */
+ sprintf(name, "sourcequench%s", codeval);
+ break;
+ case ICMP_REDIRECT: /* 5 */
+ switch (code) {
+ case ICMP_REDIRECT_NET: /* 0 */
+ return("redirect/net");
+ case ICMP_REDIRECT_HOST: /* 1 */
+ return("redirect/host");
+ case ICMP_REDIRECT_TOSNET: /* 2 */
+ return("redirect/tosnet");
+ case ICMP_REDIRECT_TOSHOST: /* 3 */
+ return("redirect/toshost");
+ default:
+ sprintf(name, "redirect/%d", code);
+ break;
+ }
+ break;
+ case ICMP_ECHO: /* 8 */
+ sprintf(name, "echo%s", codeval);
+ break;
+ case ICMP_ROUTERADVERT: /* 9 */
+ sprintf(name, "routeradvert%s", codeval);
+ break;
+ case ICMP_ROUTERSOLICIT: /* 10 */
+ sprintf(name, "routersolicit%s", codeval);
+ break;
+ case ICMP_TIMXCEED: /* 11 */
+ switch (code) {
+ case ICMP_TIMXCEED_INTRANS: /* 0 */
+ return("timxceed/intrans");
+ case ICMP_TIMXCEED_REASS: /* 1 */
+ return("timxceed/reass");
+ default:
+ sprintf(name, "timxceed/%d", code);
+ break;
+ }
+ break;
+ case ICMP_PARAMPROB: /* 12 */
+ switch (code) {
+ case ICMP_PARAMPROB_OPTABSENT: /* 1 */
+ return("paramprob/optabsent");
+ default:
+ sprintf(name, "paramprob/%d", code);
+ break;
+ }
+ break;
+ case ICMP_TSTAMP: /* 13 */
+ sprintf(name, "tstamp%s", codeval);
+ break;
+ case ICMP_TSTAMPREPLY: /* 14 */
+ sprintf(name, "tstampreply%s", codeval);
+ break;
+ case ICMP_IREQ: /* 15 */
+ sprintf(name, "ireq%s", codeval);
+ break;
+ case ICMP_IREQREPLY: /* 16 */
+ sprintf(name, "ireqreply%s", codeval);
+ break;
+ case ICMP_MASKREQ: /* 17 */
+ sprintf(name, "maskreq%s", codeval);
+ break;
+ case ICMP_MASKREPLY: /* 18 */
+ sprintf(name, "maskreply%s", codeval);
+ break;
+ default:
+ sprintf(name, "%d/%d", type, code);
+ break;
+ }
+
+ return name;
+ }
+
+
static void dumphex(log, buf, len)
FILE *log;
u_char *buf;
***************
*** 741,749 ****
ic = (struct icmp *)((char *)ip + hl);
(void) sprintf(t, "%s -> ", hostname(res, v, s));
t += strlen(t);
! (void) sprintf(t, "%s PR icmp len %hu %hu icmp %d/%d",
hostname(res, v, d), hl, plen,
! ic->icmp_type, ic->icmp_code);
if (ic->icmp_type == ICMP_UNREACH ||
ic->icmp_type == ICMP_SOURCEQUENCH ||
ic->icmp_type == ICMP_PARAMPROB ||
--- 868,876 ----
ic = (struct icmp *)((char *)ip + hl);
(void) sprintf(t, "%s -> ", hostname(res, v, s));
t += strlen(t);
! (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s",
hostname(res, v, d), hl, plen,
! icmpname((u_int) ic->icmp_type, (u_int) ic->icmp_code));
if (ic->icmp_type == ICMP_UNREACH ||
ic->icmp_type == ICMP_SOURCEQUENCH ||
ic->icmp_type == ICMP_PARAMPROB ||
***************
*** 881,887 ****
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) {
--- 1008,1014 ----
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) {
***************
*** 944,950 ****
int fd[3], doread, n, i;
int tr, nr, regular[3], c;
int fdt[3], devices = 0, make_daemon = 0;
! char buf[512], *iplfile[3], *s;
extern int optind;
extern char *optarg;
--- 1071,1077 ----
int fd[3], doread, n, i;
int tr, nr, regular[3], c;
int fdt[3], devices = 0, make_daemon = 0;
! char buf[512], *iplfile[3];
extern int optind;
extern char *optarg;
***************
*** 954,959 ****
--- 1081,1088 ----
iplfile[1] = IPNAT_NAME;
iplfile[2] = IPSTATE_NAME;
+ argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0];
+
while ((c = getopt(argc, argv, "?abDf:FhnN:o:O:pP:sS:tvxX")) != -1)
switch (c)
{
***************
*** 1004,1017 ****
pidfile = optarg;
break;
case 's' :
! s = strrchr(argv[0], '/');
! if (s == NULL)
! s = argv[0];
! else
! s++;
! openlog(s, LOG_NDELAY|LOG_PID, LOGFAC);
! s = NULL;
opts |= OPT_SYSLOG;
break;
case 'S' :
opts |= OPT_STATE;
--- 1133,1141 ----
pidfile = optarg;
break;
case 's' :
! openlog(argv0, LOG_NDELAY|LOG_PID, LOGFAC);
opts |= OPT_SYSLOG;
+ log = NULL; /* don't log to stdout any more! */
break;
case 'S' :
opts |= OPT_STATE;
***************
*** 1033,1039 ****
default :
case 'h' :
case '?' :
! usage(argv[0]);
}
init_tabs();
--- 1157,1163 ----
default :
case 'h' :
case '?' :
! usage(argv0);
}
init_tabs();
***************
*** 1054,1066 ****
(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++;
--- 1178,1191 ----
(void) fprintf(stderr,
"%s: open: %s\n", iplfile[i],
STRERROR(errno));
! exit(1);
! /* NOTREACHED */
}
if (fstat(fd[i], &sb) == -1) {
(void) fprintf(stderr, "%d: fstat: %s\n",fd[i],
STRERROR(errno));
! exit(1);
! /* NOTREACHED */
}
if (!(regular[i] = !S_ISCHR(sb.st_mode)))
devices++;
***************
*** 1071,1095 ****
logfile = argv[optind];
log = logfile ? fopen(logfile, "a") : stdout;
if (log == NULL) {
-
(void) fprintf(stderr, "%s: fopen: %s\n", argv[optind],
STRERROR(errno));
! exit(-1);
}
setvbuf(log, NULL, _IONBF, 0);
} else
log = NULL;
if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) {
! if (fork() > 0)
exit(0);
! write_pid(pidfile);
close(0);
close(1);
! close(2);
! setsid();
! } else
! write_pid(pidfile);
signal(SIGHUP, handlehup);
--- 1196,1231 ----
logfile = argv[optind];
log = logfile ? fopen(logfile, "a") : stdout;
if (log == NULL) {
(void) fprintf(stderr, "%s: fopen: %s\n", argv[optind],
STRERROR(errno));
! exit(1);
! /* NOTREACHED */
}
setvbuf(log, NULL, _IONBF, 0);
} else
log = NULL;
if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) {
! #if BSD
! daemon(0, !(opts & OPT_SYSLOG));
! #else
! int pid;
! if ((pid = fork()) > 0)
exit(0);
! if (pid < 0) {
! (void) fprintf(stderr, "%s: fork() failed: %s\n", argv0,
! STRERROR(errno));
! exit(1);
! /* NOTREACHED */
! }
! setsid();
! if (!(opts & OPT_SYSLOG))
! close(2);
! #endif /* !BSD */
close(0);
close(1);
! }
! write_pid(pidfile);
signal(SIGHUP, handlehup);
***************
*** 1102,1109 ****
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);
--- 1238,1249 ----
continue;
if (!regular[i]) {
if (ioctl(fd[i], FIONREAD, &tr) == -1) {
! if (opts & OPT_SYSLOG)
! syslog(LOG_CRIT, "ioctl(FIONREAD): %m");
! else
! perror("ioctl(FIONREAD)");
! exit(1);
! /* NOTREACHED */
}
} else {
tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size);
***************
*** 1128,1141 ****
{
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;
--- 1268,1281 ----
{
case -1 :
if (opts & OPT_SYSLOG)
! syslog(LOG_CRIT, "read: %m\n");
else
perror("read");
doread = 0;
break;
case 1 :
if (opts & OPT_SYSLOG)
! syslog(LOG_CRIT, "aborting logging\n");
else
fprintf(log, "aborting logging\n");
doread = 0;