From 820076e1d48f75a6cdcb65e2a97a19f42e2c2734 Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Thu, 11 Oct 2007 23:47:59 +0000 Subject: [PATCH] Ranges might want masks too. git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@2616 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- lib/vserver.h | 34 +++++++----- src/naddress.c | 160 +++++++++++++++++++++++++++++++-------------------------- 2 files changed, 107 insertions(+), 87 deletions(-) diff --git a/lib/vserver.h b/lib/vserver.h index bbc8049..bc21f78 100644 --- a/lib/vserver.h +++ b/lib/vserver.h @@ -632,20 +632,26 @@ extern "C" { uint16_t vna_flags; uint16_t vna_prefix; uint16_t vna_parent; - union { - struct { - struct in_addr ip; - struct in_addr mask; - } ipv4; - struct { - struct in6_addr ip; - struct in6_addr mask; - } ipv6; - } u; -#define vna_v4_ip u.ipv4.ip -#define vna_v4_mask u.ipv4.mask -#define vna_v6_ip u.ipv6.ip -#define vna_v6_mask u.ipv6.mask + struct { + union { + struct in_addr v4; + struct in6_addr v6; + } ip; + union { + struct in_addr v4; + struct in6_addr v6; + } ip2; + union { + struct in_addr v4; + struct in6_addr v6; + } mask; + } s; +#define vna_v4_ip s.ip.v4 +#define vna_v4_ip2 s.ip2.v6 +#define vna_v4_mask s.mask.v4 +#define vna_v6_ip s.ip.v6 +#define vna_v6_ip2 s.ip2.v6 +#define vna_v6_mask s.mask.v6 }; struct vc_net_flags { diff --git a/src/naddress.c b/src/naddress.c index f413e49..349e2d7 100644 --- a/src/naddress.c +++ b/src/naddress.c @@ -237,94 +237,94 @@ maskToPrefix(void *data, int limit) return prefix; } -static void -readIP(char const *str, struct vc_ips **ips, uint16_t type) +static int +parseIPFormat(char const *str_c, struct vc_ips **ips, + char const *format) { - if (ifconfig_getaddr(str, &(*ips)->a.vna_v4_ip.s_addr, &(*ips)->a.vna_v4_mask.s_addr, NULL)==-1) { - char *pt; - char tmpopt[strlen(str)+1]; + size_t len = strlen(str_c); + char const *fc; + char str[len + 1], *ptr = str; + int ret = -1; + + strcpy(str, str_c); + + /* XXX: condition at the bottom */ + for (fc = format; ; fc += 2) { + char *sep; + void *dst; + unsigned long limit = 0; + + switch (*fc) { + case '1': dst = &(*ips)->a.s.ip; break; + case '2': dst = &(*ips)->a.s.ip2; break; + case 'm': dst = &(*ips)->a.s.mask; break; + default: goto out; + } - strcpy(tmpopt,str); - pt = strchr(tmpopt,'/'); - if (pt) - *pt++ = '\0'; + if ((sep = memchr(ptr, *(fc + 1), len)) == NULL) { + goto out; + } + *sep = '\0'; - if (convertAddress(tmpopt, &(*ips)->a.vna_type, &(*ips)->a.vna_v4_ip.s_addr) == -1) { - WRITE_MSG(2, "Invalid IP number '"); - WRITE_STR(2, tmpopt); - WRITE_MSG(2, "'\n"); - exit(wrapper_exit_code); + /* This is ugly, and means that m cannot be first */ + switch ((*ips)->a.vna_type) { + case VC_NXA_TYPE_IPV4: limit = 32; break; + case VC_NXA_TYPE_IPV6: limit = 128; break; } - if (pt==0) { + /* This is required due to the dain-bramage that is inet_pton in dietlibc. + * Essentially any number will be parsed as a valid IPv4 address... + */ + if (*fc == 'm' && strchr(ptr, ':') == NULL && strchr(ptr, '.') == NULL) { + /* This is a prefix, not a netmask */ + unsigned long sz; + + if (!isNumberUnsigned(ptr, &sz, true) || sz > limit) { + goto out; + } + + (*ips)->a.vna_prefix = sz; switch ((*ips)->a.vna_type) { case VC_NXA_TYPE_IPV4: - (*ips)->a.vna_v4_mask.s_addr = htonl(0xffffff00); - (*ips)->a.vna_prefix = 24; + (*ips)->a.vna_v4_mask.s_addr = htonl(~((1 << (32 - sz)) - 1)); break; case VC_NXA_TYPE_IPV6: - (*ips)->a.vna_prefix = 64; - (*ips)->a.vna_v6_mask.s6_addr32[0] = (*ips)->a.vna_v6_mask.s6_addr32[1] = 0xffffffff; - (*ips)->a.vna_v6_mask.s6_addr32[2] = (*ips)->a.vna_v6_mask.s6_addr32[3] = 0x00000000; + ipv6PrefixToMask(&(*ips)->a.vna_v6_mask, sz); break; - default: break; } } else { - // Ok, we have a network size, not a netmask - if (strchr(pt,'.')==0 && strchr(pt,':')==0) { - unsigned long sz, limit = 0; - - switch ((*ips)->a.vna_type) { - case VC_NXA_TYPE_IPV4: limit = 32; break; - case VC_NXA_TYPE_IPV6: limit = 128; break; - default: break; - } - - if (!isNumberUnsigned(pt, &sz, true) || sz > limit) { - WRITE_MSG(2, "Invalid prefix '"); - WRITE_STR(2, pt); - WRITE_MSG(2, "'\n"); - exit(wrapper_exit_code); - } - - (*ips)->a.vna_prefix = sz; - switch ((*ips)->a.vna_type) { - case VC_NXA_TYPE_IPV4: - (*ips)->a.vna_v4_mask.s_addr = htonl(~((1 << (32 - sz)) - 1)); - break; - case VC_NXA_TYPE_IPV6: - ipv6PrefixToMask(&(*ips)->a.vna_v6_mask, (*ips)->a.vna_prefix); - break; - default: break; - } + if (convertAddress(ptr, &(*ips)->a.vna_type, dst) == -1) { + goto out; } - else { - int af, limit; - void *mask; - switch ((*ips)->a.vna_type) { - case VC_NXA_TYPE_IPV4: - af = AF_INET; - mask = &(*ips)->a.vna_v4_mask.s_addr; - limit = 32; - break; - case VC_NXA_TYPE_IPV6: - af = AF_INET6; - mask = (*ips)->a.vna_v6_mask.s6_addr32; - limit = 128; - break; - default: - return; - } - if (inet_pton(af, pt, mask) < 0) { - WRITE_MSG(2, "Invalid netmask '"); - WRITE_STR(2, pt); - WRITE_MSG(2, "'\n"); - exit(wrapper_exit_code); - } - (*ips)->a.vna_prefix = maskToPrefix(mask, limit); + else if (*fc == 'm') { + /* Got a mask, set the prefix */ + (*ips)->a.vna_prefix = maskToPrefix(&(*ips)->a.s.mask, limit); } } + + ptr = sep + 1; + + if (*(fc + 1) == '\0') + break; + } + ret = 0; + +out: + free(str); + return ret; +} + +static void +readIP(char const *str, struct vc_ips **ips, uint16_t type) +{ + if (ifconfig_getaddr(str, &(*ips)->a.vna_v4_ip.s_addr, &(*ips)->a.vna_v4_mask.s_addr, NULL)==-1) { + if (parseIPFormat(str, ips, "1/m") == -1) { + WRITE_MSG(2, "Invalid IP number '"); + WRITE_STR(2, str); + WRITE_MSG(2, "'\n"); + exit(wrapper_exit_code); + } } else (*ips)->a.vna_type = VC_NXA_TYPE_IPV4; @@ -353,6 +353,20 @@ readBcast(char const *str, struct vc_ips **ips) } static void +readRange(char const *str, struct vc_ips **ips) +{ + if (parseIPFormat(str, ips, "1-2/m") == -1) { + WRITE_MSG(2, "Invalid range '"); + WRITE_STR(2, str); + WRITE_MSG(2, "'\n"); + exit(wrapper_exit_code); + } + (*ips)->a.vna_type |= VC_NXA_TYPE_RANGE; + (*ips)->next = calloc(1, sizeof(struct vc_ips)); + *ips = (*ips)->next; +} + +static void tellAddress(struct vc_net_addr *addr, bool silent) { char buf[41]; @@ -452,7 +466,7 @@ int main (int argc, char *argv[]) case CMD_SET : args.do_set = true; break; case CMD_IP : readIP(optarg, &ips, VC_NXA_TYPE_ADDR); break; case CMD_MASK : readIP(optarg, &ips, VC_NXA_TYPE_MASK); break; - case CMD_RANGE : readIP(optarg, &ips, VC_NXA_TYPE_RANGE); break; + case CMD_RANGE : readRange(optarg, &ips); break; case CMD_BCAST : readBcast(optarg, &ips); break; case CMD_LBACK : readIP(optarg, &ips, VC_NXA_TYPE_ADDR | VC_NXA_MOD_LBACK); break; default : -- 1.8.1.5