summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarchie <archie@FreeBSD.org>1999-01-22 01:46:32 +0000
committerarchie <archie@FreeBSD.org>1999-01-22 01:46:32 +0000
commitd2ea85ad411ebd2cab7131d96637d835d08fd6a8 (patch)
tree1a6fb3b095b7db0b45da93d9f326418b9c6500a3
parenta3349fcd1f5b971dc1d4d2373179351287b5fc47 (diff)
downloadFreeBSD-src-d2ea85ad411ebd2cab7131d96637d835d08fd6a8.zip
FreeBSD-src-d2ea85ad411ebd2cab7131d96637d835d08fd6a8.tar.gz
Fix bug where 'ipfw list' would choke if there were a large number of rules.
-rw-r--r--sbin/ipfw/ipfw.c174
1 files changed, 95 insertions, 79 deletions
diff --git a/sbin/ipfw/ipfw.c b/sbin/ipfw/ipfw.c
index 22e794d..191818c 100644
--- a/sbin/ipfw/ipfw.c
+++ b/sbin/ipfw/ipfw.c
@@ -16,7 +16,7 @@
*
* NEW command line interface for IP firewall facility
*
- * $Id: ipfw.c,v 1.63 1998/12/14 18:43:03 luigi Exp $
+ * $Id: ipfw.c,v 1.64 1998/12/27 11:23:05 luigi Exp $
*
*/
@@ -420,75 +420,85 @@ list(ac, av)
int ac;
char **av;
{
- struct ip_fw *r;
- struct ip_fw rules[1024];
- struct dn_pipe *p;
- struct dn_pipe pipes[1024];
- int l,i,bytes;
- unsigned long rulenum;
+ struct ip_fw *rules;
+ struct dn_pipe *pipes;
+ void *data = NULL;
int pcwidth = 0;
int bcwidth = 0;
+ int n, num = 0;
- /* extract rules from kernel */
- if (do_pipe) {
- memset(rules,0,sizeof pipes);
- bytes = sizeof pipes;
- i = getsockopt(s, IPPROTO_IP, IP_DUMMYNET_GET, pipes, &bytes);
- if (i < 0)
- err(2,"getsockopt(IP_DUMMYNET_GET)");
- /* display requested pipes */
- if (ac > 0)
- rulenum = strtoul(*av++, NULL, 10);
- else
- rulenum = 0 ;
- for (p = pipes, l = bytes; l >= sizeof pipes[0];
- p++, l-=sizeof pipes[0]) {
- if (rulenum == 0 || rulenum == p->pipe_nr) {
- double b = p->bandwidth ;
- int l ;
- char buf[30] ;
- char qs[30] ;
- char plr[30] ;
-
- if (b == 0)
- sprintf(buf, "unlimited");
- else if (b >= 1000000)
- sprintf(buf, "%7.3f Mbit/s", b/1000000 );
- else if (b >= 1000)
- sprintf(buf, "%7.3f Kbit/s", b/1000 );
- else
- sprintf(buf, "%7.3f bit/s ", b );
-
- if ( (l = p->queue_size_bytes) ) {
- if (l >= 8192)
- sprintf(qs,"%d KB", l / 1024);
- else
- sprintf(qs,"%d B", l);
- } else
- sprintf(qs,"%3d sl.", p->queue_size);
- if (p->plr)
- sprintf(plr,"plr %f", 1.0*p->plr/(double)(0x7fffffff));
- else
- plr[0]='\0';
-
- printf("%05d: %s %4d ms %s %s -- %d pkts (%d B) %d drops\n",
- p->pipe_nr, buf, p->delay, qs, plr,
- p->r_len, p->r_len_bytes, p->r_drops);
- }
- }
-
- return ;
- }
+ /* get rules or pipes from kernel, resizing array as necessary */
+ {
+ const int unit = do_pipe ? sizeof(*pipes) : sizeof(*rules);
+ const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET;
+ int nalloc = 0;
+ int nbytes;
+
+ while (num >= nalloc) {
+ nalloc = nalloc * 2 + 200;
+ nbytes = nalloc * unit;
+ if ((data = realloc(data, nbytes)) == NULL)
+ err(EX_OSERR, "realloc");
+ if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0)
+ err(EX_OSERR, "getsockopt(IP_%s_GET)",
+ do_pipe ? "DUMMYNET" : "FW");
+ num = nbytes / unit;
+ }
+ }
+
+ /* display requested pipes */
+ if (do_pipe) {
+ u_long rulenum;
+
+ pipes = (struct dn_pipe *) data;
+ if (ac > 0)
+ rulenum = strtoul(*av++, NULL, 10);
+ else
+ rulenum = 0 ;
+ for (n = 0; n < num; n++) {
+ struct dn_pipe *const p = &pipes[n];
+ double b = p->bandwidth ;
+ char buf[30] ;
+ char qs[30] ;
+ char plr[30] ;
+ int l ;
+
+ if (rulenum != 0 && rulenum != p->pipe_nr)
+ continue;
+ if (b == 0)
+ sprintf(buf, "unlimited");
+ else if (b >= 1000000)
+ sprintf(buf, "%7.3f Mbit/s", b/1000000 );
+ else if (b >= 1000)
+ sprintf(buf, "%7.3f Kbit/s", b/1000 );
+ else
+ sprintf(buf, "%7.3f bit/s ", b );
+
+ if ( (l = p->queue_size_bytes) != 0 ) {
+ if (l >= 8192)
+ sprintf(qs,"%d KB", l / 1024);
+ else
+ sprintf(qs,"%d B", l);
+ } else
+ sprintf(qs,"%3d sl.", p->queue_size);
+ if (p->plr)
+ sprintf(plr,"plr %f", 1.0*p->plr/(double)(0x7fffffff));
+ else
+ plr[0]='\0';
+
+ printf("%05d: %s %4d ms %s %s -- %d pkts (%d B) %d drops\n",
+ p->pipe_nr, buf, p->delay, qs, plr,
+ p->r_len, p->r_len_bytes, p->r_drops);
+ }
+ free(data);
+ return;
+ }
- memset(rules,0,sizeof rules);
- bytes = sizeof rules;
- i = getsockopt(s, IPPROTO_IP, IP_FW_GET, rules, &bytes);
- if (i < 0)
- err(2,"getsockopt(IP_FW_GET)");
- if (do_acct)
- /* find the maximum packet/byte counter widths */
- for (r=rules, l = bytes; l >= sizeof rules[0];
- r++, l-=sizeof rules[0]) {
+ /* if showing stats, figure out column widths ahead of time */
+ rules = (struct ip_fw *) data;
+ if (do_acct) {
+ for (n = 0; n < num; n++) {
+ struct ip_fw *const r = &rules[n];
char temp[32];
int width;
@@ -502,45 +512,51 @@ list(ac, av)
if (width > bcwidth)
bcwidth = width;
}
- if (!ac) {
+ }
+ if (ac == 0) {
/* display all rules */
- for (r = rules, l = bytes; l >= sizeof rules[0];
- r++, l-=sizeof rules[0])
+ for (n = 0; n < num; n++) {
+ struct ip_fw *const r = &rules[n];
+
show_ipfw(r, pcwidth, bcwidth);
- }
- else {
+ }
+ } else {
/* display specific rules requested on command line */
int exitval = EX_OK;
while (ac--) {
+ u_long rnum;
char *endptr;
int seen;
/* convert command line rule # */
- rulenum = strtoul(*av++, &endptr, 10);
+ rnum = strtoul(*av++, &endptr, 10);
if (*endptr) {
exitval = EX_USAGE;
- warn("invalid rule number: %s", *(av - 1));
+ warnx("invalid rule number: %s", *(av - 1));
continue;
}
- seen = 0;
- for (r = rules, l = bytes;
- l >= sizeof rules[0] && r->fw_number <= rulenum;
- r++, l-=sizeof rules[0])
- if (rulenum == r->fw_number) {
+ for (seen = n = 0; n < num; n++) {
+ struct ip_fw *const r = &rules[n];
+
+ if (r->fw_number > rnum)
+ break;
+ if (r->fw_number == rnum) {
show_ipfw(r, pcwidth, bcwidth);
seen = 1;
}
+ }
if (!seen) {
/* give precedence to other error(s) */
if (exitval == EX_OK)
exitval = EX_UNAVAILABLE;
- warnx("rule %lu does not exist", rulenum);
+ warnx("rule %lu does not exist", rnum);
}
}
if (exitval != EX_OK)
exit(exitval);
}
+ free(data);
}
static void
OpenPOWER on IntegriCloud