Subject: Re: printing ICMP type/subtype codes with ipmon
To: None <netbsd-users@netbsd.org>
From: Greg A. Woods <woods@weird.com>
List: netbsd-users
Date: 12/10/2001 13:13:16
[ On Monday, December 10, 2001 at 08:54:47 (-0700), Steve Bellovin wrote: ]
> Subject: printing ICMP type/subtype codes with ipmon
>
> Here are some changes to the 1.5.2 ipmon so that it prints ICMP type
> and subtype codes symbolically. I know that this is external code
> imported into NetBSD, so I've sent it off to Darren as well, but folks
> may want to use it now regardless of when or if it's integrated into
> the base source.
Too bad you had to re-invent that patch -- I made a similar change to
ipmon way back in late 1998 in my 1.3.3 source tree. I though I had
sent Darren my patch too, but I may not have (I can't find the string
'icmpname' in any of my outgoing e-mail archives). Attached is the
patch from my -current (still 2001/06/24) tree.
There are some other unrelated fixes in my patch too (of course! :-)
(I've got a bunch of other minor fixes to IP Filter and its
documentation that I should look over an forward to Darren too....)
--
Greg A. Woods
+1 416 218-0098; <gwoods@acm.org>; <g.a.woods@ieee.org>; <woods@robohack.ca>
Planix, Inc. <woods@planix.com>; VE3TCP; 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 -r1.1.1.4 ipmon.c
*** ipmon.c 12 Jun 2001 21:03:00 -0000 1.1.1.4
--- ipmon.c 4 Jul 2001 21:28:11 -0000
***************
*** 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,141 ****
static char **protocols = NULL;
static char **udp_ports = NULL;
static char **tcp_ports = NULL;
!
#define OPT_SYSLOG 0x001
#define OPT_RESOLVE 0x002
--- 136,142 ----
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
***************
*** 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;