From a218a37d8f3992628173cf0f30749bbb145dcbf7 Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 9 May 2004 04:12:03 +0000 Subject: [PATCH] PR/25122: Peter Postma: ipfstat state top broken with IPv6 addresses patch applied. --- dist/ipf/man/ipfstat.8 | 36 ++-- dist/ipf/tools/ipfstat.c | 447 +++++++++++++++++++++++++++------------ 2 files changed, 329 insertions(+), 154 deletions(-) diff --git a/dist/ipf/man/ipfstat.8 b/dist/ipf/man/ipfstat.8 index d18dfebf48cb..968e63ccd07c 100644 --- a/dist/ipf/man/ipfstat.8 +++ b/dist/ipf/man/ipfstat.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: ipfstat.8,v 1.10 2004/03/28 09:00:56 martti Exp $ +.\" $NetBSD: ipfstat.8,v 1.11 2004/05/09 04:12:03 christos Exp $ .\" .TH ipfstat 8 .SH NAME @@ -6,12 +6,12 @@ ipfstat \- reports on packet filter statistics and filter list .SH SYNOPSIS .B ipfstat [ -.B \-6aACdfghIinosv +.B \-6aAdfghIilnoRsv ] - +.br .B ipfstat -t [ -.B \-C +.B \-6C ] [ .B \-D @@ -26,7 +26,6 @@ ipfstat \- reports on packet filter statistics and filter list ] .SH DESCRIPTION -.PP \fBipfstat\fP examines /dev/kmem using the symbols \fB_fr_flags\fP, \fB_frstats\fP, \fB_filterin\fP, and \fB_filterout\fP. To run and work, it needs to be able to read both /dev/kmem and the @@ -38,7 +37,7 @@ accumulated over time as the kernel has put packets through the filter. .SH OPTIONS .TP .B \-6 -Display filter lists for IPv6, if available. +Display filter lists and states for IPv6, if available. .TP .B \-a Display the accounting filter list and show bytes counted against each rule. @@ -58,7 +57,7 @@ Produce debugging output when displaying data. .BR \-D \0 This option is only valid in combination with \fB\-t\fP. Limit the state top display to show only state entries whose destination IP address and port -match the addport argument. The addrport specification is of the form +match the addrport argument. The addrport specification is of the form ipaddress[,port]. The ipaddress and port should be either numerical or the string "any" (specifying any IP address resp. any port). If the \fB\-D\fP option is not specified, it defaults to "\fB\-D\fP any,any". @@ -94,6 +93,10 @@ argument can be a protocol name (as defined in \fB/etc/protocols\fP) or a protocol number. If this option is not specified, state entries for any protocol are specified. .TP +.BR \-R +Don't try to resolve addresses to hostnames and ports to services while +printing statistics. +.TP .B \-s Show packet/flow state information (statistics only). .TP @@ -103,14 +106,14 @@ Show held state information (in the kernel) if any is present (no statistics). .BR \-S \0 This option is only valid in combination with \fB\-t\fP. Limit the state top display to show only state entries whose source IP address and port match -the addport argument. The addrport specification is of the form +the addrport argument. The addrport specification is of the form ipaddress[,port]. The ipaddress and port should be either numerical or the string "any" (specifying any IP address resp. any port). If the \fB\-S\fP option is not specified, it defaults to "\fB\-S\fP any,any". .TP .B \-t -Show the state table in a way similar to they way \fBtop(1)\fP shows the process -table. States can be sorted using a number of different ways. This options +Show the state table in a way similar to the way \fBtop(1)\fP shows the process +table. States can be sorted using a number of different ways. This option requires \fBcurses(3)\fP and needs to be compiled in. It may not be available on all operating systems. See below, for more information on the keys that can be used while ipfstat is in top mode. @@ -142,7 +145,9 @@ shown and to specify the frequency of display updates. In state top mode, the following keys can be used to influence the displayed information: .TP -\fBd\fP select information to display. +\fBb\fP show packets/bytes from backward direction. +.TP +\fBf\fP show packets/bytes from forward direction. (default) .TP \fBl\fP redraw the screen. .TP @@ -162,13 +167,12 @@ and protocol filters or the refresh frequency. This must be done from the command line. .PP The screen must have at least 80 columns. This is however not checked. +When running state top in IPv6 mode, the screen must be much wider to display +the very long IPv6 addresses. .PP Only the first X-5 entries that match the sort and filter criteria are -displayed (where X is the number of rows on the display. There is no way to -see more entries. -.PP -No support for IPv6 -.PP +displayed (where X is the number of rows on the display. The only way to see +more entries is to resize the screen. .SH FILES /dev/kmem .br diff --git a/dist/ipf/tools/ipfstat.c b/dist/ipf/tools/ipfstat.c index c9ad2eba220a..17a2785d9a72 100644 --- a/dist/ipf/tools/ipfstat.c +++ b/dist/ipf/tools/ipfstat.c @@ -1,4 +1,4 @@ -/* $NetBSD: ipfstat.c,v 1.3 2004/04/07 20:27:54 christos Exp $ */ +/* $NetBSD: ipfstat.c,v 1.4 2004/05/09 04:12:03 christos Exp $ */ /* * Copyright (C) 1993-2001, 2003 by Darren Reed. @@ -29,7 +29,7 @@ #include "netinet/ipl.h" #if defined(STATETOP) # if defined(_BSDI_VERSION) -# undef STATETOP) +# undef STATETOP # endif # if defined(__FreeBSD__) && \ (!defined(__FreeBSD_version) || (__FreeBSD_version < 430000)) @@ -52,6 +52,7 @@ #endif #ifdef STATETOP # include +# include # if SOLARIS || defined(__NetBSD__) || defined(_BSDI_VERSION) || \ defined(__sgi) # ifdef ERR @@ -78,6 +79,7 @@ static const char rcsid[] = "@(#)Id: ipfstat.c,v 1.44.2.4 2004/03/19 23:06:50 da extern char *optarg; extern int optind; +extern int opterr; #define PRINTF (void)printf #define FPRINTF (void)fprintf @@ -116,6 +118,7 @@ typedef struct statetop { u_short st_sport; u_short st_dport; u_char st_p; + u_char st_v; u_char st_state[2]; U_QUAD_T st_pkts; U_QUAD_T st_bytes; @@ -123,22 +126,27 @@ typedef struct statetop { } statetop_t; #endif -extern int main __P((int, char *[])); +int main __P((int, char *[])); + static void showstats __P((friostat_t *, u_32_t)); static void showfrstates __P((ipfrstat_t *)); static void showlist __P((friostat_t *)); static void showipstates __P((ips_stat_t *)); static void showauthstates __P((fr_authstat_t *)); static void showgroups __P((friostat_t *)); -static void Usage __P((char *)); +static void usage __P((char *)); static void printlist __P((frentry_t *, char *)); -static void parse_ipportstr __P((const char *, struct in_addr *, int *)); +static void parse_ipportstr __P((const char *, i6addr_t *, int *)); static void ipfstate_live __P((char *, friostat_t **, ips_stat_t **, ipfrstat_t **, fr_authstat_t **, u_32_t *)); static void ipfstate_dead __P((char *, friostat_t **, ips_stat_t **, ipfrstat_t **, fr_authstat_t **, u_32_t *)); #ifdef STATETOP -static void topipstates __P((struct in_addr, struct in_addr, int, int, int, int, int)); +static void topipstates __P((i6addr_t, i6addr_t, int, int, int, + int, int, int)); +static void sig_break __P((int)); +static void sig_resize __P((int)); +static char *getip __P((int, i6addr_t *)); static char *ttl_to_string __P((long)); static int sort_p __P((const void *, const void *)); static int sort_pkts __P((const void *, const void *)); @@ -149,16 +157,21 @@ static int sort_dstip __P((const void *, const void *)); #endif -static void Usage(name) +static void usage(name) char *name; { #ifdef USE_INET6 - fprintf(stderr, "Usage: %s [-6aACdfghIilnoRstv] [-d ]\n", name); + fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name); #else - fprintf(stderr, "Usage: %s [-aACdfghIilnoRstv] [-d ]\n", name); + fprintf(stderr, "Usage: %s [-aAdfghIilnoRsv]\n", name); #endif - fprintf(stderr, "\t\t[-M corefile] [-N symbol-list]\n"); - fprintf(stderr, " %s -t [-S source address] [-D destination address] [-P protocol] [-T refreshtime] [-C] [-d ]\n", name); + fprintf(stderr, " %s [-M corefile] [-N symbol-list]\n", name); +#ifdef USE_INET6 + fprintf(stderr, " %s -t [-6C] ", name); +#else + fprintf(stderr, " %s -t [-C] ", name); +#endif + fprintf(stderr, "[-D destination address] [-P protocol] [-S source address] [-T refresh time]\n"); exit(1); } @@ -176,7 +189,7 @@ char *argv[]; ipfrstat_t ifrst; ipfrstat_t *ifrstp = &ifrst; char *device = IPL_NAME, *memf = NULL; - char *kern = NULL; + char *options, *kern = NULL; int c, myoptind; int protocol = -1; /* -1 = wild card for any protocol */ @@ -184,18 +197,31 @@ char *argv[]; int sport = -1; /* -1 = wild card for any source port */ int dport = -1; /* -1 = wild card for any dest port */ int topclosed = 0; /* do not show closed tcp sessions */ - struct in_addr saddr, daddr; + i6addr_t saddr, daddr; u_32_t frf; - saddr.s_addr = INADDR_ANY; /* default any source addr */ - daddr.s_addr = INADDR_ANY; /* default any dest addr */ +#ifdef USE_INET6 + options = "6aACdfghIilnostvD:M:N:P:RS:T:"; +#else + options = "aACdfghIilnostvD:M:N:P:RS:T:"; +#endif + + saddr.in4.s_addr = INADDR_ANY; /* default any v4 source addr */ + daddr.in4.s_addr = INADDR_ANY; /* default any v4 dest addr */ +#ifdef USE_INET6 + saddr.in6 = in6addr_any; /* default any v6 source addr */ + daddr.in6 = in6addr_any; /* default any v6 dest addr */ +#endif + + /* Don't warn about invalid flags when we run getopt for the 1st time */ + opterr = 0; /* * Parse these two arguments now lest there be any buffer overflows * in the parsing of the rest. */ myoptind = optind; - while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:RS:T:")) != -1) + while ((c = getopt(argc, argv, options)) != -1) { switch (c) { case 'M' : @@ -207,6 +233,7 @@ char *argv[]; live_kernel = 0; break; } + } optind = myoptind; if (live_kernel == 1) { @@ -221,8 +248,7 @@ char *argv[]; } } - if (kern != NULL || memf != NULL) - { + if (kern != NULL || memf != NULL) { (void)setgid(getgid()); (void)setuid(getuid()); } @@ -235,7 +261,9 @@ char *argv[]; (void)setgid(getgid()); (void)setuid(getuid()); - while ((c = getopt(argc, argv, "6aACdfghIilnostvD:M:N:P:RS:T:")) != -1) + opterr = 1; + + while ((c = getopt(argc, argv, options)) != -1) { switch (c) { @@ -290,7 +318,7 @@ char *argv[]; case 'P' : protocol = getproto(optarg); if (protocol == -1) { - fprintf(stderr, "%s : Invalid protocol: %s\n", + fprintf(stderr, "%s: Invalid protocol: %s\n", argv[0], optarg); exit(-2); } @@ -310,7 +338,7 @@ char *argv[]; break; #else fprintf(stderr, - "%s : state top facility not compiled in\n", + "%s: state top facility not compiled in\n", argv[0]); exit(-2); #endif @@ -318,7 +346,7 @@ char *argv[]; if (!sscanf(optarg, "%d", &refreshtime) || (refreshtime <= 0)) { fprintf(stderr, - "%s : Invalid refreshtime < 1 : %s\n", + "%s: Invalid refreshtime < 1 : %s\n", argv[0], optarg); exit(-2); } @@ -327,7 +355,7 @@ char *argv[]; opts |= OPT_VERBOSE; break; default : - Usage(argv[0]); + usage(argv[0]); break; } } @@ -350,21 +378,20 @@ char *argv[]; opts &= ~OPT_OUTQUE; showlist(fiop); } - } else { - if (opts & OPT_FRSTATES) - showfrstates(ifrstp); + } else if (opts & OPT_FRSTATES) + showfrstates(ifrstp); #ifdef STATETOP - else if (opts & OPT_STATETOP) - topipstates(saddr, daddr, sport, dport, - protocol, refreshtime, topclosed); + else if (opts & OPT_STATETOP) + topipstates(saddr, daddr, sport, dport, protocol, + use_inet6 ? 6 : 4, refreshtime, topclosed); #endif - else if (opts & OPT_AUTHSTATS) - showauthstates(frauthstp); - else if (opts & OPT_GROUPS) - showgroups(fiop); - else - showstats(fiop, frf); - } + else if (opts & OPT_AUTHSTATS) + showauthstates(frauthstp); + else if (opts & OPT_GROUPS) + showgroups(fiop); + else + showstats(fiop, frf); + return 0; } @@ -962,19 +989,23 @@ ips_stat_t *ipsp; #ifdef STATETOP -static void topipstates(saddr, daddr, sport, dport, protocol, +static int handle_resize = 0, handle_break = 0; + +static void topipstates(saddr, daddr, sport, dport, protocol, ver, refreshtime, topclosed) -struct in_addr saddr; -struct in_addr daddr; +i6addr_t saddr; +i6addr_t daddr; int sport; int dport; int protocol; +int ver; int refreshtime; int topclosed; { char str1[STSTRSIZE], str2[STSTRSIZE], str3[STSTRSIZE], str4[STSTRSIZE]; int maxtsentries = 0, reverse = 0, sorting = STSORT_DEFAULT; - int i, j, winx, tsentry, maxx, maxy, redraw = 0; + int i, j, winy, tsentry, maxx, maxy, redraw = 0; + int len, srclen, dstlen, forward = 1, c = 0; ips_stat_t ipsst, *ipsstp = &ipsst; statetop_t *tstable = NULL, *tp; ipstate_t ips; @@ -983,18 +1014,26 @@ int topclosed; char hostnm[HOSTNMLEN]; struct protoent *proto; fd_set readfd; - int c = 0; time_t t; + /* install signal handlers */ + signal(SIGINT, sig_break); + signal(SIGQUIT, sig_break); + signal(SIGTERM, sig_break); + signal(SIGWINCH, sig_resize); + /* init ncurses stuff */ initscr(); cbreak(); noecho(); + curs_set(0); + timeout(0); + getmaxyx(stdscr, maxy, maxx); /* init hostname */ gethostname(hostnm, sizeof(hostnm) - 1); hostnm[sizeof(hostnm) - 1] = '\0'; - + /* init ipfobj_t stuff */ bzero((caddr_t)&ipfo, sizeof(ipfo)); ipfo.ipfo_rev = IPFILTER_VERSION; @@ -1015,66 +1054,103 @@ int topclosed; /* clear the history */ tsentry = -1; + /* reset max str len */ + srclen = dstlen = 0; + /* read the state table and store in tstable */ - while (ipsstp->iss_list) { + for (; ipsstp->iss_list; ipsstp->iss_list = ips.is_next) { + if (kmemcpy((char *)&ips, (u_long)ipsstp->iss_list, sizeof(ips))) break; - ipsstp->iss_list = ips.is_next; - if (((saddr.s_addr == INADDR_ANY) || - (saddr.s_addr == ips.is_saddr)) && - ((daddr.s_addr == INADDR_ANY) || - (daddr.s_addr == ips.is_daddr)) && - ((protocol < 0) || (protocol == ips.is_p)) && - (((ips.is_p != IPPROTO_TCP) && - (ips.is_p != IPPROTO_UDP)) || - (((sport < 0) || - (htons(sport) == ips.is_sport)) && - ((dport < 0) || - (htons(dport) == ips.is_dport)))) && - (topclosed || (ips.is_p != IPPROTO_TCP) || - (ips.is_state[0] < IPF_TCPS_LAST_ACK) || - (ips.is_state[1] < IPF_TCPS_LAST_ACK))) { - /* - * if necessary make room for this state - * entry - */ - tsentry++; - if (!maxtsentries || - (tsentry == maxtsentries)) { + if (ips.is_v != ver) + continue; - maxtsentries += STGROWSIZE; - tstable = realloc(tstable, maxtsentries * sizeof(statetop_t)); - if (!tstable) { - perror("malloc"); - exit(-1); - } + /* check v4 src/dest addresses */ + if (ips.is_v == 4) { + if ((saddr.in4.s_addr != INADDR_ANY && + saddr.in4.s_addr != ips.is_saddr) || + (daddr.in4.s_addr != INADDR_ANY && + daddr.in4.s_addr != ips.is_daddr)) + continue; + } +#ifdef USE_INET6 + /* check v6 src/dest addresses */ + if (ips.is_v == 6) { + if ((IP6_NEQ(&saddr, &in6addr_any) && + IP6_NEQ(&saddr, &ips.is_src)) || + (IP6_NEQ(&daddr, &in6addr_any) && + IP6_NEQ(&daddr, &ips.is_dst))) + continue; + } +#endif + /* check protocol */ + if (protocol > 0 && protocol != ips.is_p) + continue; + + /* check ports if protocol is TCP or UDP */ + if (((ips.is_p == IPPROTO_TCP) || + (ips.is_p == IPPROTO_UDP)) && + (((sport > 0) && (htons(sport) != ips.is_sport)) || + ((dport > 0) && (htons(dport) != ips.is_dport)))) + continue; + + /* show closed TCP sessions ? */ + if ((topclosed == 0) && (ips.is_p == IPPROTO_TCP) && + (ips.is_state[0] >= IPF_TCPS_LAST_ACK) && + (ips.is_state[1] >= IPF_TCPS_LAST_ACK)) + continue; + + /* + * if necessary make room for this state + * entry + */ + tsentry++; + if (!maxtsentries || tsentry == maxtsentries) { + maxtsentries += STGROWSIZE; + tstable = realloc(tstable, + maxtsentries * sizeof(statetop_t)); + if (tstable == NULL) { + perror("realloc"); + exit(-1); } + } - /* fill structure */ - tp = tstable + tsentry; - tp->st_src = ips.is_src; - tp->st_dst = ips.is_dst; - tp->st_p = ips.is_p; - tp->st_state[0] = ips.is_state[0]; - tp->st_state[1] = ips.is_state[1]; - tp->st_pkts = ips.is_pkts[0] + ips.is_pkts[1]; - tp->st_bytes = ips.is_bytes[0] + - ips.is_bytes[1]; - tp->st_age = ips.is_die - ipsstp->iss_ticks; - if ((ips.is_p == IPPROTO_TCP) || - (ips.is_p == IPPROTO_UDP)) { - tp->st_sport = ips.is_sport; - tp->st_dport = ips.is_dport; - } + /* get max src/dest address string length */ + len = strlen(getip(ips.is_v, &ips.is_src)); + if (srclen < len) + srclen = len; + len = strlen(getip(ips.is_v, &ips.is_dst)); + if (dstlen < len) + dstlen = len; + /* fill structure */ + tp = tstable + tsentry; + tp->st_src = ips.is_src; + tp->st_dst = ips.is_dst; + tp->st_p = ips.is_p; + tp->st_v = ips.is_v; + tp->st_state[0] = ips.is_state[0]; + tp->st_state[1] = ips.is_state[1]; + if (forward) { + tp->st_pkts = ips.is_pkts[0]+ips.is_pkts[1]; + tp->st_bytes = ips.is_bytes[0]+ips.is_bytes[1]; + } else { + tp->st_pkts = ips.is_pkts[2]+ips.is_pkts[3]; + tp->st_bytes = ips.is_bytes[2]+ips.is_bytes[3]; + } + tp->st_age = ips.is_die - ipsstp->iss_ticks; + if ((ips.is_p == IPPROTO_TCP) || + (ips.is_p == IPPROTO_UDP)) { + tp->st_sport = ips.is_sport; + tp->st_dport = ips.is_dport; } } /* sort the array */ - if (tsentry != -1) + if (tsentry != -1) { switch (sorting) { case STSORT_PR: @@ -1104,13 +1180,30 @@ int topclosed; default: break; } + } + + /* handle window resizes */ + if (handle_resize) { + endwin(); + initscr(); + cbreak(); + noecho(); + curs_set(0); + timeout(0); + getmaxyx(stdscr, maxy, maxx); + redraw = 1; + handle_resize = 0; + } + + /* stop program? */ + if (handle_break) + break; /* print title */ erase(); - getmaxyx(stdscr, maxy, maxx); attron(A_BOLD); - winx = 0; - move(winx,0); + winy = 0; + move(winy,0); sprintf(str1, "%s - %s - state top", hostnm, IPL_VERSION); for (j = 0 ; j < (maxx - 8 - strlen(str1)) / 2; j++) printw(" "); @@ -1118,7 +1211,7 @@ int topclosed; attroff(A_BOLD); /* just for fun add a clock */ - move(winx, maxx - 8); + move(winy, maxx - 8); t = time(NULL); strftime(str1, 80, "%T", localtime(&t)); printw("%s\n", str1); @@ -1129,14 +1222,14 @@ int topclosed; * while the programming is running :-) */ if (sport >= 0) - sprintf(str1, "%s,%d", inet_ntoa(saddr), sport); + sprintf(str1, "%s,%d", getip(ver, &saddr), sport); else - sprintf(str1, "%s", inet_ntoa(saddr)); + sprintf(str1, "%s", getip(ver, &saddr)); if (dport >= 0) - sprintf(str2, "%s,%d", inet_ntoa(daddr), dport); + sprintf(str2, "%s,%d", getip(ver, &daddr), dport); else - sprintf(str2, "%s", inet_ntoa(daddr)); + sprintf(str2, "%s", getip(ver, &daddr)); if (protocol < 0) strcpy(str3, "any"); @@ -1160,10 +1253,10 @@ int topclosed; sprintf(str4, "ttl"); break; case STSORT_SRCIP: - sprintf(str4, "srcip"); + sprintf(str4, "src ip"); break; case STSORT_DSTIP: - sprintf(str4, "dstip"); + sprintf(str4, "dest ip"); break; default: sprintf(str4, "unknown"); @@ -1173,17 +1266,24 @@ int topclosed; if (reverse) strcat(str4, " (reverse)"); - winx += 2; - move(winx,0); - printw("Src = %s Dest = %s Proto = %s Sorted by = %s\n\n", + winy += 2; + move(winy,0); + printw("Src: %s, Dest: %s, Proto: %s, Sorted by: %s\n\n", str1, str2, str3, str4); + /* need at least 14 + 7 characters */ + if (srclen < 14) + srclen = 14; + if (dstlen < 14) + dstlen = 14; + /* print column description */ - winx += 2; - move(winx,0); + winy += 2; + move(winy,0); attron(A_BOLD); - printw("%-21s %-21s %3s %4s %7s %9s %9s\n", "Source IP", - "Destination IP", "ST", "PR", "#pkts", "#bytes", "ttl"); + printw("%-*s %-*s %3s %4s %7s %9s %9s\n", + srclen + 7, "Source IP", dstlen + 7, "Destination IP", + "ST", "PR", "#pkts", "#bytes", "ttl"); attroff(A_BOLD); /* print all the entries */ @@ -1198,25 +1298,27 @@ int topclosed; if ((tp->st_p == IPPROTO_TCP) || (tp->st_p == IPPROTO_UDP)) { sprintf(str1, "%s,%hu", - inet_ntoa(tp->st_src.in4), + getip(tp->st_v, &tp->st_src), ntohs(tp->st_sport)); sprintf(str2, "%s,%hu", - inet_ntoa(tp->st_dst.in4), + getip(tp->st_v, &tp->st_dst), ntohs(tp->st_dport)); } else { - sprintf(str1, "%s", inet_ntoa(tp->st_src.in4)); - sprintf(str2, "%s", inet_ntoa(tp->st_dst.in4)); + sprintf(str1, "%s", getip(tp->st_v, + &tp->st_src)); + sprintf(str2, "%s", getip(tp->st_v, + &tp->st_dst)); } - winx++; - move(winx, 0); - printw("%-21s %-21s", str1, str2); + winy++; + move(winy, 0); + printw("%-*s %-*s", srclen + 7, str1, dstlen + 7, str2); /* print state */ sprintf(str1, "%X/%X", tp->st_state[0], tp->st_state[1]); printw(" %3s", str1); - /* print proto */ + /* print protocol */ proto = getprotobynumber(tp->st_p); if (proto) { strncpy(str1, proto->p_name, 4); @@ -1224,8 +1326,12 @@ int topclosed; } else { sprintf(str1, "%d", tp->st_p); } + /* just print icmp for IPv6-ICMP */ + if (tp->st_p == IPPROTO_ICMPV6) + strcpy(str1, "icmp"); printw(" %4s", str1); - /* print #pkt/#bytes */ + + /* print #pkt/#bytes */ #ifdef USE_QUAD_T printw(" %7qu %9qu", (unsigned long long) tp->st_pkts, (unsigned long long) tp->st_bytes); @@ -1264,23 +1370,27 @@ int topclosed; if (c == ERR) continue; - if (tolower(c) == 'l') { + if (isalpha(c) && isupper(c)) + c = tolower(c); + if (c == 'l') { redraw = 1; - } else if (tolower(c) == 'q') { - nocbreak(); - endwin(); - exit(0); - } else if (tolower(c) == 'r') { + } else if (c == 'q') { + break; + } else if (c == 'r') { reverse = !reverse; - } else if (tolower(c) == 's') { - sorting++; - if (sorting > STSORT_MAX) + } else if (c == 'b') { + forward = 0; + } else if (c == 'f') { + forward = 1; + } else if (c == 's') { + if (++sorting > STSORT_MAX) sorting = 0; } } } /* while */ printw("\n"); + curs_set(1); nocbreak(); endwin(); @@ -1405,11 +1515,11 @@ struct friostat *fiop; static void parse_ipportstr(argument, ip, port) const char *argument; -struct in_addr *ip; +i6addr_t *ip; int *port; { - char *s, *comma; + int ok = 0; /* make working copy of argument, Theoretically you must be able * to write to optarg, but that seems very ugly to me.... @@ -1435,8 +1545,16 @@ int *port; /* get ip address */ if (!strcasecmp(s, "any")) { - ip->s_addr = INADDR_ANY; - } else if (!inet_aton(s, ip)) { + ip->in4.s_addr = INADDR_ANY; +#ifdef USE_INET6 + ip->in6 = in6addr_any; + } else if (use_inet6 && inet_pton(AF_INET6, s, &ip->in6)) { + ok = 1; +#endif + } else if (inet_aton(s, &ip->in4)) + ok = 1; + + if (ok == 0) { fprintf(stderr, "Invalid IP address: %s\n", s); free(s); exit(-2); @@ -1448,12 +1566,41 @@ int *port; #ifdef STATETOP -static char ttlbuf[STSTRSIZE]; +static void sig_resize(s) +int s; +{ + handle_resize = 1; +} + +static void sig_break(s) +int s; +{ + handle_break = 1; +} + +static char *getip(v, addr) +int v; +i6addr_t *addr; +{ + static char hostbuf[MAXHOSTNAMELEN+1]; + + if (v == 4) + return inet_ntoa(addr->in4); + +#ifdef USE_INET6 + (void) inet_ntop(AF_INET6, &addr->in6, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; + return hostbuf; +#else + return "IPv6"; +#endif +} + static char *ttl_to_string(ttl) long int ttl; { - + static char ttlbuf[STSTRSIZE]; int hours, minutes, seconds; /* ttl is in half seconds */ @@ -1464,7 +1611,7 @@ long int ttl; minutes = ttl / 60; seconds = ttl % 60; - if (hours > 0 ) + if (hours > 0) sprintf(ttlbuf, "%2d:%02d:%02d", hours, minutes, seconds); else sprintf(ttlbuf, "%2d:%02d", minutes, seconds); @@ -1539,10 +1686,22 @@ const void *b; register const statetop_t *ap = a; register const statetop_t *bp = b; - if (ntohl(ap->st_src.in4.s_addr) == ntohl(bp->st_src.in4.s_addr)) - return 0; - else if (ntohl(ap->st_src.in4.s_addr) > ntohl(bp->st_src.in4.s_addr)) - return 1; +#ifdef USE_INET6 + if (use_inet6) { + if (IP6_EQ(&ap->st_src, &bp->st_src)) + return 0; + else if (IP6_GT(&ap->st_src, &bp->st_src)) + return 1; + } else +#endif + { + if (ntohl(ap->st_src.in4.s_addr) == + ntohl(bp->st_src.in4.s_addr)) + return 0; + else if (ntohl(ap->st_src.in4.s_addr) > + ntohl(bp->st_src.in4.s_addr)) + return 1; + } return -1; } @@ -1553,10 +1712,22 @@ const void *b; register const statetop_t *ap = a; register const statetop_t *bp = b; - if (ntohl(ap->st_dst.in4.s_addr) == ntohl(bp->st_dst.in4.s_addr)) - return 0; - else if (ntohl(ap->st_dst.in4.s_addr) > ntohl(bp->st_dst.in4.s_addr)) - return 1; +#ifdef USE_INET6 + if (use_inet6) { + if (IP6_EQ(&ap->st_dst, &bp->st_dst)) + return 0; + else if (IP6_GT(&ap->st_dst, &bp->st_dst)) + return 1; + } else +#endif + { + if (ntohl(ap->st_dst.in4.s_addr) == + ntohl(bp->st_dst.in4.s_addr)) + return 0; + else if (ntohl(ap->st_dst.in4.s_addr) > + ntohl(bp->st_dst.in4.s_addr)) + return 1; + } return -1; } #endif