PR/25122: Peter Postma: ipfstat state top broken with IPv6 addresses

patch applied.
This commit is contained in:
christos 2004-05-09 04:12:03 +00:00
parent 865c473c96
commit a218a37d8f
2 changed files with 329 additions and 154 deletions

View File

@ -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
<addrport>
@ -26,7 +26,6 @@ ipfstat \- reports on packet filter statistics and filter list
<refresh time>
]
.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<addrport>
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<addrport>
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

View File

@ -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 <ctype.h>
# include <signal.h>
# 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 <device>]\n", name);
fprintf(stderr, "Usage: %s [-6aAdfghIilnoRsv]\n", name);
#else
fprintf(stderr, "Usage: %s [-aACdfghIilnoRstv] [-d <device>]\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 <device>]\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