- char* path;
- unsigned xid;
- struct vcmd_ctx_dlimit_base_v0 init;
- struct vcmd_ctx_dlimit_v0 data;
- int r;
-
- memset(&data,0,sizeof(data));
- if (!PyArg_ParseTuple(args, "siiiiii", &path,
- &xid,
- &data.space_used,
- &data.space_total,
- &data.inodes_used,
- &data.inodes_total,
- &data.reserved))
- return NULL;
-
- data.name = path;
- data.flags = 0;
-
- memset(&init, 0, sizeof(init));
- init.name = path;
- init.flags = 0;
-
- r = vserver(VCMD_rem_dlimit, xid, &init);
- if (r<0){}
- r = vserver(VCMD_add_dlimit, xid, &init);
- if (r<0){}
- r = vserver(VCMD_set_dlimit, xid, &data);
- if (r<0){}
- return Py_None;
+ const struct AF_to_vcNET *i;
+ for (i = converter; i->af; i++) {
+ if (inet_pton(i->af, str, dst)) {
+ *type = i->vc_net;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int
+get_mask(struct vc_net_nx *addr)
+{
+ const struct AF_to_vcNET *i;
+ struct ifaddrs *head, *ifa;
+ int ret = 0;
+
+ for (i = converter; i->af; i++) {
+ if (i->vc_net == addr->type)
+ break;
+ }
+ if (!i) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (getifaddrs(&head) == -1)
+ return -1;
+ for (ifa = head; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family == i->af &&
+ memcmp((char *) ifa->ifa_addr + i->offset, addr->ip, i->len) == 0) {
+ switch (addr->type) {
+ case vcNET_IPV4:
+ memcpy(&addr->mask[0], ifa->ifa_netmask + i->offset, i->len);
+ break;
+ case vcNET_IPV6: {
+ uint32_t *m = ((struct sockaddr_in6 *) ifa->ifa_netmask)->sin6_addr.s6_addr32;
+ /* optimization for the common case */
+ if ((m[1] & 1) == 1 && (m[2] & 0x80000000) == 0)
+ addr->mask[0] = 64;
+ else {
+ addr->mask[0] = 0;
+ while (m[addr->mask[0] / 32] & (addr->mask[0] % 32))
+ addr->mask[0]++;
+ }
+ break;
+ }
+ ret = 1;
+ break;
+ }
+ }
+ /* no match, use a default */
+ if (!ret) {
+ switch (addr->type) {
+ case vcNET_IPV4: addr->mask[0] = htonl(0xffffff00); break;
+ case vcNET_IPV6: addr->mask[0] = 64; break;
+ default: addr->mask[0] = 0; break;
+ }
+ }
+ freeifaddrs(head);
+ return ret;
+}
+
+/* XXX These two functions are really similar */
+static PyObject *
+vserver_net_add(PyObject *self, PyObject *args)
+{
+ struct vc_net_nx addr;
+ nid_t nid;
+ const char *ip;
+
+ if (!PyArg_ParseTuple(args, "Is", &nid, &ip))
+ return NULL;
+
+ if (convert_address(ip, &addr.type, &addr.ip) == -1)
+ return PyErr_Format(PyExc_ValueError, "%s is not a valid IP address", ip);
+
+ switch (get_mask(&addr)) {
+ case -1:
+ return PyErr_SetFromErrno(PyExc_OSError);
+ case 0:
+ /* XXX error here? */
+ break;
+ }
+ addr.count = 1;
+
+ if (vc_net_add(nid, &addr) == -1 && errno != ESRCH)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ return NONE;
+}
+
+static PyObject *
+vserver_net_remove(PyObject *self, PyObject *args)
+{
+ struct vc_net_nx addr;
+ nid_t nid;
+ const char *ip;
+
+ if (!PyArg_ParseTuple(args, "Is", &nid, &ip))
+ return NULL;
+
+ if (strcmp(ip, "all") == 0)
+ addr.type = vcNET_ANY;
+ else if (strcmp(ip, "all4") == 0)
+ addr.type = vcNET_IPV4A;
+ else if (strcmp(ip, "all6") == 0)
+ addr.type = vcNET_IPV6A;
+ else
+ if (convert_address(ip, &addr.type, &addr.ip) == -1)
+ return PyErr_Format(PyExc_ValueError, "%s is not a valid IP address", ip);
+
+ switch (get_mask(&addr)) {
+ case -1:
+ return PyErr_SetFromErrno(PyExc_OSError);
+ }
+ addr.count = 1;
+
+ if (vc_net_remove(nid, &addr) == -1 && errno != ESRCH)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ return NONE;