if (ipset->iprange.set)
{
- fw3_pr(" range %s", fw3_address_to_string(&ipset->iprange, false));
+ fw3_pr(" range %s", fw3_address_to_string(&ipset->iprange, false, true));
}
else if (ipset->portrange.set)
{
}
-static void
-ip4prefix2mask(int prefix, struct in_addr *mask)
-{
- if (prefix > 0)
- mask->s_addr = htonl(~((1 << (32 - prefix)) - 1));
- else
- mask->s_addr = 0;
-}
-
-#ifndef DISABLE_IPV6
-static void
-ip6prefix2mask(int prefix, struct in6_addr *mask)
-{
- char *p = (char *)mask;
-
- if (prefix > 0)
- {
- memset(p, 0xff, prefix / 8);
- memset(p + (prefix / 8) + 1, 0, (128 - prefix) / 8);
- p[prefix / 8] = 0xff << (8 - (prefix & 7));
- }
- else
- {
- memset(mask, 0, sizeof(*mask));
- }
-}
-#endif
-
void
fw3_ipt_rule_src_dest(struct fw3_ipt_rule *r,
struct fw3_address *src, struct fw3_address *dest)
if (src->range)
{
fw3_ipt_rule_addarg(r, src->invert, "--src-range",
- fw3_address_to_string(src, false));
+ fw3_address_to_string(src, false, false));
}
#ifndef DISABLE_IPV6
else if (r->h->family == FW3_FAMILY_V6)
{
r->e6.ipv6.src = src->address.v6;
- ip6prefix2mask(src->mask, &r->e6.ipv6.smsk);
+ r->e6.ipv6.smsk = src->mask.v6;
int i;
for (i = 0; i < 4; i++)
else
{
r->e.ip.src = src->address.v4;
- ip4prefix2mask(src->mask, &r->e.ip.smsk);
+ r->e.ip.smsk = src->mask.v4;
r->e.ip.src.s_addr &= r->e.ip.smsk.s_addr;
if (dest->range)
{
fw3_ipt_rule_addarg(r, dest->invert, "--dst-range",
- fw3_address_to_string(dest, false));
+ fw3_address_to_string(dest, false, false));
}
#ifndef DISABLE_IPV6
else if (r->h->family == FW3_FAMILY_V6)
{
r->e6.ipv6.dst = dest->address.v6;
- ip6prefix2mask(dest->mask, &r->e6.ipv6.dmsk);
+ r->e6.ipv6.dmsk = dest->mask.v6;
int i;
for (i = 0; i < 4; i++)
else
{
r->e.ip.dst = dest->address.v4;
- ip4prefix2mask(dest->mask, &r->e.ip.dmsk);
+ r->e.ip.dmsk = dest->mask.v4;
r->e.ip.dst.s_addr &= r->e.ip.dmsk.s_addr;
static void
rule_print6(struct ip6t_entry *e)
{
- char buf[INET6_ADDRSTRLEN];
+ char buf1[INET6_ADDRSTRLEN], buf2[INET6_ADDRSTRLEN];
char *pname;
if (e->ipv6.flags & IP6T_F_PROTO)
if (e->ipv6.flags & IP6T_INV_SRCIP)
printf(" !");
- printf(" -s %s/%u", inet_ntop(AF_INET6, &e->ipv6.src, buf, sizeof(buf)),
- xtables_ip6mask_to_cidr(&e->ipv6.smsk));
+ printf(" -s %s/%s",
+ inet_ntop(AF_INET6, &e->ipv6.src, buf1, sizeof(buf1)),
+ inet_ntop(AF_INET6, &e->ipv6.smsk, buf2, sizeof(buf2)));
}
if (memcmp(&e->ipv6.dst, &in6addr_any, sizeof(struct in6_addr)))
if (e->ipv6.flags & IP6T_INV_DSTIP)
printf(" !");
- printf(" -d %s/%u", inet_ntop(AF_INET6, &e->ipv6.dst, buf, sizeof(buf)),
- xtables_ip6mask_to_cidr(&e->ipv6.dmsk));
+ printf(" -d %s/%s",
+ inet_ntop(AF_INET6, &e->ipv6.dst, buf1, sizeof(buf1)),
+ inet_ntop(AF_INET6, &e->ipv6.dmsk, buf2, sizeof(buf2)));
}
}
#endif
rule_print4(struct ipt_entry *e)
{
struct in_addr in_zero = { 0 };
- char buf[sizeof("255.255.255.255\0")];
+ char buf1[sizeof("255.255.255.255\0")], buf2[sizeof("255.255.255.255\0")];
char *pname;
if (e->ip.proto)
if (e->ip.flags & IPT_INV_SRCIP)
printf(" !");
- printf(" -s %s/%u", inet_ntop(AF_INET, &e->ip.src, buf, sizeof(buf)),
- xtables_ipmask_to_cidr(&e->ip.smsk));
+ printf(" -s %s/%s",
+ inet_ntop(AF_INET, &e->ip.src, buf1, sizeof(buf1)),
+ inet_ntop(AF_INET, &e->ip.smsk, buf2, sizeof(buf2)));
}
if (memcmp(&e->ip.dst, &in_zero, sizeof(struct in_addr)))
if (e->ip.flags & IPT_INV_DSTIP)
printf(" !");
- printf(" -d %s/%u", inet_ntop(AF_INET, &e->ip.dst, buf, sizeof(buf)),
- xtables_ipmask_to_cidr(&e->ip.dmsk));
+ printf(" -d %s/%s",
+ inet_ntop(AF_INET, &e->ip.dst, buf1, sizeof(buf1)),
+ inet_ntop(AF_INET, &e->ip.dmsk, buf2, sizeof(buf2)));
}
}
struct fw3_address addr = { };
struct in_addr v4;
struct in6_addr v6;
- char *p, *s, *e;
- int i, m = -1;
+ char *p = NULL, *m = NULL, *s, *e;
+ int bits = -1;
if (*val == '!')
{
if (!s)
return false;
- if ((p = strchr(s, '/')) != NULL)
- {
+ if ((m = strchr(s, '/')) != NULL)
+ *m++ = 0;
+ else if ((p = strchr(s, '-')) != NULL)
*p++ = 0;
- m = strtoul(p, &e, 10);
- if ((e == p) || (*e != 0))
- {
- if (strchr(s, ':') || !inet_pton(AF_INET, p, &v4))
- {
- free(s);
- return false;
- }
-
- for (i = 0, m = 32; !(v4.s_addr & 1) && (i < 32); i++)
- {
- m--;
- v4.s_addr >>= 1;
- }
- }
- }
- else if ((p = strchr(s, '-')) != NULL)
+ if (inet_pton(AF_INET6, s, &v6))
{
- *p++ = 0;
+ addr.family = FW3_FAMILY_V6;
+ addr.address.v6 = v6;
- if (inet_pton(AF_INET6, p, &v6))
+ if (m && !inet_pton(AF_INET6, m, &addr.mask.v6))
{
- addr.family = FW3_FAMILY_V6;
- addr.address2.v6 = v6;
- addr.range = true;
+ bits = strtol(m, &e, 10);
+
+ if ((*e != 0) || !fw3_bitlen2netmask(addr.family, bits, &v6))
+ goto fail;
+
+ addr.mask.v6 = v6;
}
- else if (inet_pton(AF_INET, p, &v4))
+ else if (p)
{
- addr.family = FW3_FAMILY_V4;
- addr.address2.v4 = v4;
+ if (!inet_pton(AF_INET6, p, &addr.mask.v6))
+ goto fail;
+
addr.range = true;
}
else
{
- free(s);
- return false;
+ memset(addr.mask.v6.s6_addr, 0xFF, 16);
}
}
-
- if (inet_pton(AF_INET6, s, &v6))
- {
- addr.family = FW3_FAMILY_V6;
- addr.address.v6 = v6;
- addr.mask = (m >= 0) ? m : 128;
- }
else if (inet_pton(AF_INET, s, &v4))
{
addr.family = FW3_FAMILY_V4;
addr.address.v4 = v4;
- addr.mask = (m >= 0) ? m : 32;
+
+ if (m && !inet_pton(AF_INET, m, &addr.mask.v4))
+ {
+ bits = strtol(m, &e, 10);
+
+ if ((*e != 0) || !fw3_bitlen2netmask(addr.family, bits, &v4))
+ goto fail;
+
+ addr.mask.v4 = v4;
+ }
+ else if (p)
+ {
+ if (!inet_pton(AF_INET, p, &addr.mask.v4))
+ goto fail;
+
+ addr.range = true;
+ }
+ else
+ {
+ addr.mask.v4.s_addr = 0xFFFFFFFF;
+ }
}
else
{
- free(s);
- return false;
+ goto fail;
}
free(s);
addr.set = true;
put_value(ptr, &addr, sizeof(addr), is_list);
return true;
+
+fail:
+ free(s);
+ return false;
}
bool
const char *
-fw3_address_to_string(struct fw3_address *address, bool allow_invert)
+fw3_address_to_string(struct fw3_address *address, bool allow_invert, bool as_cidr)
{
char *p, ip[INET6_ADDRSTRLEN];
static char buf[INET6_ADDRSTRLEN * 2 + 2];
if (address->range)
{
inet_ntop(address->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
- &address->address2.v4, ip, sizeof(ip));
+ &address->mask.v4, ip, sizeof(ip));
p += sprintf(p, "-%s", ip);
}
+ else if (!as_cidr)
+ {
+ inet_ntop(address->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
+ &address->mask.v4, ip, sizeof(ip));
+
+ p += sprintf(p, "/%s", ip);
+ }
else
{
- p += sprintf(p, "/%u", address->mask);
+ p += sprintf(p, "/%u", fw3_netmask2bitlen(address->family,
+ &address->mask.v6));
}
return buf;
bool invert;
bool resolved;
enum fw3_family family;
- int mask;
union {
struct in_addr v4;
struct in6_addr v6;
struct in_addr v4;
struct in6_addr v6;
struct ether_addr mac;
- } address2;
+ } mask;
};
struct fw3_mac
struct blob_attr *a);
const char * fw3_address_to_string(struct fw3_address *address,
- bool allow_invert);
+ bool allow_invert, bool as_cidr);
#endif
static bool
compare_addr(struct fw3_address *a, struct fw3_address *b)
{
- uint32_t mask;
-
if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4)
return false;
- mask = htonl(~((1 << (32 - a->mask)) - 1));
-
- return ((a->address.v4.s_addr & mask) == (b->address.v4.s_addr & mask));
+ return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
+ (b->address.v4.s_addr & a->mask.v4.s_addr));
}
static bool
else
ref_addr = *ext_addr;
- ref_addr.mask = 32;
- ext_addr->mask = 32;
+ ref_addr.mask.v4.s_addr = 0xFFFFFFFF;
+ ext_addr->mask.v4.s_addr = 0xFFFFFFFF;
print_reflection(handle, state, redir, num, proto,
&ref_addr, int_addr, ext_addr);
{
if (!strcmp(blobmsg_name(cur), "address"))
inet_pton(family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
- blobmsg_data(cur), &addr->address.v6);
+ blobmsg_get_string(cur), &addr->address.v6);
else if (!strcmp(blobmsg_name(cur), "mask"))
- addr->mask = be32_to_cpu(*(uint32_t *)blobmsg_data(cur));
+ fw3_bitlen2netmask(family, blobmsg_get_u32(cur), &addr->mask.v6);
}
return addr;
if (!sub)
continue;
- ptr.value = fw3_address_to_string(sub, true);
+ ptr.value = fw3_address_to_string(sub, true, false);
uci_add_list(ctx, &ptr);
}
{
ptr.o = NULL;
ptr.option = "iprange";
- ptr.value = fw3_address_to_string(&s->iprange, false);
+ ptr.value = fw3_address_to_string(&s->iprange, false, false);
uci_set(ctx, &ptr);
}
/* unreached */
return false;
}
+
+int
+fw3_netmask2bitlen(int family, void *mask)
+{
+ int bits;
+ struct in_addr *v4;
+ struct in6_addr *v6;
+
+ if (family == FW3_FAMILY_V6)
+ for (bits = 0, v6 = mask;
+ bits < 128 && (v6->s6_addr[bits / 8] << (bits % 8)) & 128;
+ bits++);
+ else
+ for (bits = 0, v4 = mask;
+ bits < 32 && (ntohl(v4->s_addr) << bits) & 0x80000000;
+ bits++);
+
+ return bits;
+}
+
+bool
+fw3_bitlen2netmask(int family, int bits, void *mask)
+{
+ int i;
+ struct in_addr *v4;
+ struct in6_addr *v6;
+
+ if (family == FW3_FAMILY_V6)
+ {
+ if (bits < -128 || bits > 128)
+ return false;
+
+ v6 = mask;
+ i = abs(bits);
+
+ memset(v6->s6_addr, 0xff, i / 8);
+ memset(v6->s6_addr + (i / 8) + 1, 0, (128 - i) / 8);
+ v6->s6_addr[i / 8] = 0xff << (8 - (i & 7));
+
+ if (bits < 0)
+ for (i = 0; i < 16; i++)
+ v6->s6_addr[i] = ~v6->s6_addr[i];
+ }
+ else
+ {
+ if (bits < -32 || bits > 32)
+ return false;
+
+ v4 = mask;
+ v4->s_addr = htonl(~((1 << (32 - abs(bits))) - 1));
+
+ if (bits < 0)
+ v4->s_addr = ~v4->s_addr;
+ }
+
+ return true;
+}
bool fw3_hotplug(bool add, void *zone, void *device);
+int fw3_netmask2bitlen(int family, void *mask);
+
+bool fw3_bitlen2netmask(int family, int bits, void *mask);
+
#endif