#define CMD_SET 0x2004
#define CMD_IP 0x2010
#define CMD_BCAST 0x2011
+#define CMD_MASK 0x2012
+#define CMD_RANGE 0x2013
+#define CMD_LBACK 0x2014
int wrapper_exit_code = 255;
{ "set", no_argument, 0, CMD_SET },
{ "nid", required_argument, 0, CMD_NID },
{ "ip", required_argument, 0, CMD_IP },
+ { "mask", required_argument, 0, CMD_MASK },
+ { "range", required_argument, 0, CMD_RANGE },
{ "bcast", required_argument, 0, CMD_BCAST },
+ { "lback", required_argument, 0, CMD_LBACK },
{ 0,0,0,0 }
};
struct vc_ips {
- struct vc_net_nx a;
+ struct vc_net_addr a;
struct vc_ips *next;
};
}
static int
-convertAddress(const char *str, vc_net_nx_type *type, void *dst)
+convertAddress(const char *str, uint16_t *type, void *dst)
{
int ret;
- if (type) *type = vcNET_IPV4;
+ if (type) *type = VC_NXA_TYPE_IPV4;
ret = inet_pton(AF_INET, str, dst);
if (ret==0) {
- if (type) *type = vcNET_IPV6;
+ if (type) *type = VC_NXA_TYPE_IPV6;
ret = inet_pton(AF_INET6, str, dst);
}
return ret > 0 ? 0 : -1;
}
static void
-readIP(char const *str, struct vc_ips **ips)
+ipv6PrefixToMask(struct in6_addr *mask, int prefix)
{
- if (ifconfig_getaddr(str, &(*ips)->a.ip[0], &(*ips)->a.mask[0], NULL)==-1) {
- char *pt;
- char tmpopt[strlen(str)+1];
- uint32_t *mask = (*ips)->a.mask;
+ int i;
+ mask->s6_addr32[0] = mask->s6_addr32[1] = mask->s6_addr32[2] = mask->s6_addr32[3] = 0;
+ for (i = 0; (i << 3) < prefix; i++) {
+ mask->s6_addr[i] = 0xff;
+ }
+ if ((i << 3) > prefix)
+ mask->s6_addr[i-1] = ~((1 << (prefix & 0x07)) - 1);
+}
- strcpy(tmpopt,str);
- pt = strchr(tmpopt,'/');
- if (pt)
- *pt++ = '\0';
+static int
+maskToPrefix(void *data, int limit)
+{
+ uint8_t *mask = data;
+ int prefix;
+ for (prefix = 0; prefix < limit && mask[prefix >> 3] & (1 << (prefix & 0x07)); prefix++)
+ ;
+ return prefix;
+}
- if (convertAddress(tmpopt, &(*ips)->a.type, (*ips)->a.ip) == -1) {
- WRITE_MSG(2, "Invalid IP number '");
- WRITE_STR(2, tmpopt);
- WRITE_MSG(2, "'\n");
- exit(wrapper_exit_code);
+static int
+parseIPFormat(char const *str_c, struct vc_ips **ips,
+ char const *format)
+{
+ size_t len = strlen(str_c);
+ char const *fc;
+ char str[len + 1], *ptr = str;
+ int ret = 0;
+
+ 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;
+ }
+
+ if (len == 0)
+ goto out;
+ if ((sep = memchr(ptr, *(fc + 1), len)) == NULL)
+ sep = ptr + len;
+ *sep = '\0';
+
+ /* 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) {
- switch ((*ips)->a.type) {
- case vcNET_IPV4:
- mask[0] = htonl(0xffffff00);
+ /* 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) {
+ ret = -1;
+ 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(~((1 << (32 - sz)) - 1));
break;
- case vcNET_IPV6:
- mask[0] = 64;
+ case VC_NXA_TYPE_IPV6:
+ 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.type) {
- case vcNET_IPV4: limit = 32; break;
- case vcNET_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);
- }
-
- switch ((*ips)->a.type) {
- case vcNET_IPV4:
- mask[0] = htonl(~((1 << (32 - sz)) - 1));
- break;
- case vcNET_IPV6:
- mask[0] = sz;
- break;
- default: break;
- }
+ if (convertAddress(ptr, &(*ips)->a.vna_type, dst) == -1) {
+ ret = -1;
+ goto out;
}
- else {
- if (convertAddress(pt, NULL, &(*ips)->a.mask) == -1) {
- WRITE_MSG(2, "Invalid netmask '");
- WRITE_STR(2, pt);
- WRITE_MSG(2, "'\n");
- exit(wrapper_exit_code);
- }
+ else if (*fc == 'm') {
+ /* Got a mask, set the prefix */
+ (*ips)->a.vna_prefix = maskToPrefix(&(*ips)->a.s.mask, limit);
}
}
+
+ ret++;
+ len -= (sep - ptr);
+ ptr = sep + 1;
+
+ if (*(fc + 1) == '\0')
+ break;
+ }
+
+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.type = vcNET_IPV4;
+ (*ips)->a.vna_type = VC_NXA_TYPE_IPV4;
+ (*ips)->a.vna_type |= type;
- (*ips)->a.count = 1;
(*ips)->next = calloc(1, sizeof(struct vc_ips));
*ips = (*ips)->next;
}
{
uint32_t bcast;
if (ifconfig_getaddr(str, NULL, NULL, &bcast)==-1){
- if (convertAddress(str, NULL, &bcast) == -1) {
+ if (inet_pton(AF_INET, str, &bcast) < 0) {
WRITE_MSG(2, "Invalid broadcast number '");
WRITE_STR(2, optarg);
WRITE_MSG(2, "'\n");
exit(wrapper_exit_code);
}
}
- (*ips)->a.ip[0] = bcast;
- (*ips)->a.count = 1;
- (*ips)->a.type = vcNET_IPV4B;
+ (*ips)->a.vna_v4_ip.s_addr = bcast;
+ (*ips)->a.vna_type = VC_NXA_TYPE_IPV4 | VC_NXA_MOD_BCAST | VC_NXA_TYPE_ADDR;
+ (*ips)->next = calloc(1, sizeof(struct vc_ips));
+ *ips = (*ips)->next;
+}
+
+static void
+readRange(char const *str, struct vc_ips **ips)
+{
+ if (parseIPFormat(str, ips, "1-2/m") < 2) {
+ 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_nx *addr, bool silent)
+tellAddress(struct vc_net_addr *addr, bool silent)
{
char buf[41];
+ int af;
+ void *address;
if (silent)
return;
- if (inet_ntop(addr->type == vcNET_IPV6 ? AF_INET6 : AF_INET,
- addr->ip, buf, sizeof(buf)) == NULL) {
+ switch (addr->vna_type & (VC_NXA_TYPE_IPV4 | VC_NXA_TYPE_IPV6)) {
+ case VC_NXA_TYPE_IPV4:
+ af = AF_INET;
+ address = &addr->vna_v4_ip.s_addr;
+ break;
+ case VC_NXA_TYPE_IPV6:
+ af = AF_INET6;
+ address = addr->vna_v6_ip.s6_addr32;
+ break;
+ default:
+ WRITE_MSG(1, " <unknown address type>");
+ return;
+ }
+ if (inet_ntop(af, address, buf, sizeof(buf)) == NULL) {
WRITE_MSG(1, " <conversion failed>");
return;
}
struct vc_ips *ips;
if (args->do_set) {
- struct vc_net_nx remove = { .type = vcNET_ANY };
+ struct vc_net_addr remove = { .vna_type = VC_NXA_TYPE_ANY };
if (vc_net_remove(args->nid, &remove) == -1) {
perror(ENSC_WRAPPERS_PREFIX "vc_net_remove()");
exit(wrapper_exit_code);
WRITE_MSG(1, "Adding");
for (ips = &args->head; ips->next; ips = ips->next) {
tellAddress(&ips->a, args->is_silent);
- if (vc_net_add(args->nid, &ips->a) != (int)ips->a.count) {
+ if (vc_net_add(args->nid, &ips->a) == -1) {
+ if (!args->is_silent)
+ WRITE_MSG(1, "\n");
perror(ENSC_WRAPPERS_PREFIX "vc_net_add()");
exit(wrapper_exit_code);
}
WRITE_MSG(1, "Removing");
for (ips = &args->head; ips->next; ips = ips->next) {
tellAddress(&ips->a, args->is_silent);
- if (vc_net_remove(args->nid, &ips->a) != (int)ips->a.count) {
+ if (vc_net_remove(args->nid, &ips->a) == -1) {
+ if (!args->is_silent)
+ WRITE_MSG(1, "\n");
perror(ENSC_WRAPPERS_PREFIX "vc_net_remove()");
exit(wrapper_exit_code);
}
case CMD_ADD : args.do_add = true; break;
case CMD_REMOVE : args.do_remove = true; break;
case CMD_SET : args.do_set = true; break;
- case CMD_IP : readIP(optarg, &ips); 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 : 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 :
WRITE_MSG(2, "Try '");
WRITE_STR(2, argv[0]);