diff options
Diffstat (limited to 'sbin/ip6fw')
-rw-r--r-- | sbin/ip6fw/ip6fw.c | 28 |
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]; |