summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ip6fw/ip6fw.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/sbin/ip6fw/ip6fw.c b/sbin/ip6fw/ip6fw.c
index 9c3a7e5..c630734 100644
--- a/sbin/ip6fw/ip6fw.c
+++ b/sbin/ip6fw/ip6fw.c
@@ -37,6 +37,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <errno.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -410,18 +411,25 @@ list(ac, av)
int ac;
char **av;
{
- struct ip6_fw *r;
- struct ip6_fw rules[1024];
+ struct ip6_fw *r, *rules;
int l,i;
unsigned long rulenum;
- int bytes;
-
- /* extract rules from kernel */
- memset(rules,0,sizeof rules);
- bytes = sizeof rules;
- i = getsockopt(s, IPPROTO_IPV6, IPV6_FW_GET, rules, &bytes);
- if (i < 0)
- err(2,"getsockopt(IPV6_FW_GET)");
+ int nalloc, bytes, maxbytes;
+
+ /* extract rules from kernel, resizing array as necessary */
+ rules = NULL;
+ nalloc = sizeof *rules;
+ bytes = nalloc;
+ maxbytes = 65536 * sizeof *rules;
+ while (bytes >= nalloc) {
+ nalloc = nalloc * 2 + 200;
+ bytes = nalloc;
+ if ((rules = realloc(rules, bytes)) == NULL)
+ err(2, "realloc");
+ i = getsockopt(s, IPPROTO_IPV6, IPV6_FW_GET, rules, &bytes);
+ if ((i < 0 && errno != EINVAL) || nalloc > maxbytes)
+ err(2, "getsockopt(IPV6_FW_GET)");
+ }
if (!ac) {
/* display all rules */
for (r = rules, l = bytes; l >= sizeof rules[0];
OpenPOWER on IntegriCloud