#define CMD_NID 0x2001
#define CMD_ADD 0x2002
#define CMD_REMOVE 0x2003
+#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;
{ "silent", no_argument, 0, CMD_SILENT },
{ "add", no_argument, 0, CMD_ADD },
{ "remove", no_argument, 0, CMD_REMOVE },
+ { "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;
};
bool is_silent;
bool do_add;
bool do_remove;
+ bool do_set;
};
static void
WRITE_MSG(fd, "Usage:\n ");
WRITE_STR(fd, cmd);
WRITE_MSG(fd,
- " [--silent] [--nid <nid>] [--ip <ip_num>[/<mask>]] [--bcast <broadcast>] [--] <commands> <args>*\n\n"
+ " (--add|--remove|--set) [--silent] [--nid <nid>]\n"
+ " [--ip <ip_num>[/<mask>]] [--bcast <broadcast>] [--] <commands> <args>*\n\n"
"Please report bugs to " PACKAGE_BUGREPORT "\n");
exit(res);
}
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) {
- int sz = atoi(pt);
- switch ((*ips)->a.type) {
- case vcNET_IPV4:
- mask[0] = htonl((1 << 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:
+ 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;
}
doit(struct Arguments *args)
{
struct vc_ips *ips;
- if (args->do_add) {
+
+ if (args->do_set) {
+ 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);
+ }
+ }
+
+ if (args->do_add || args->do_set) {
if (!args->is_silent)
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);
}
.is_silent = false,
.do_add = false,
.do_remove = false,
+ .do_set = false,
.head = { .next = NULL },
};
struct vc_ips *ips = &args.head;
if (c==-1) break;
switch (c) {
- case CMD_HELP : showHelp(1, argv[0], 0);
- case CMD_VERSION : showVersion();
- case CMD_SILENT : args.is_silent = true; break;
- case CMD_BCAST : readBcast(optarg, &ips); break;
- case CMD_NID : args.nid = Evc_nidopt2nid(optarg,true); break;
- case CMD_ADD : args.do_add = true; break;
- case CMD_REMOVE : args.do_remove = true; break;
- case CMD_IP : readIP(optarg, &ips); break;
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_SILENT : args.is_silent = true; break;
+ case CMD_NID : args.nid = Evc_nidopt2nid(optarg,true); break;
+ 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, 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]);
- WRITE_MSG(2, " --help\" for more information.\n");
+ WRITE_MSG(2, " --help' for more information.\n");
exit(wrapper_exit_code);
break;
}
if (args.nid == VC_NOCTX) args.nid = Evc_get_task_nid(0);
- if (!args.do_add && !args.do_remove) {
+ if (!args.do_add && !args.do_remove && !args.do_set) {
WRITE_MSG(2, "No operation specified; try '--help' for more information\n");
exit(wrapper_exit_code);
}
- else if (args.do_add && args.do_remove) {
+ else if (((args.do_add ? 1 : 0) + (args.do_remove ? 1 : 0) + (args.do_set ? 1 : 0)) > 1) {
WRITE_MSG(2, "Multiple operations specified; try '--help' for more information\n");
exit(wrapper_exit_code);
}