static char *iptablesFormatNetwork(virSocketAddr *netaddr, unsigned int prefix) { virSocketAddr network; char *netstr; char *ret; if (!(VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET) || VIR_SOCKET_ADDR_IS_FAMILY(netaddr, AF_INET6))) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Only IPv4 or IPv6 addresses can be used with iptables")); return NULL; } if (virSocketAddrMaskByPrefix(netaddr, prefix, &network) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failure to mask address")); return NULL; } netstr = virSocketAddrFormat(&network); if (!netstr) return NULL; if (virAsprintf(&ret, "%s/%d", netstr, prefix) < 0) virReportOOMError(); VIR_FREE(netstr); return ret; }
static int testMaskNetwork(const char *addrstr, int prefix, const char *networkstr) { virSocketAddr addr; virSocketAddr network; char *gotnet = NULL; /* Intentionally fill with garbage */ memset(&network, 1, sizeof(network)); if (virSocketAddrParse(&addr, addrstr, AF_UNSPEC) < 0) return -1; if (virSocketAddrMaskByPrefix(&addr, prefix, &network) < 0) return -1; if (!(gotnet = virSocketAddrFormat(&network))) return -1; if (STRNEQ(networkstr, gotnet)) { VIR_FREE(gotnet); fprintf(stderr, "Expected %s, got %s\n", networkstr, gotnet); return -1; } VIR_FREE(gotnet); return 0; }
virNetDevIPRoutePtr virNetDevIPRouteCreate(const char *errorDetail, const char *family, const char *address, const char *netmask, const char *gateway, unsigned int prefix, bool hasPrefix, unsigned int metric, bool hasMetric) { virNetDevIPRoutePtr def = NULL; virSocketAddr testAddr; if (VIR_ALLOC(def) < 0) return NULL; if (VIR_STRDUP(def->family, family) < 0) goto error; def->prefix = prefix; def->has_prefix = hasPrefix; def->metric = metric; def->has_metric = hasMetric; /* Note: both network and gateway addresses must be specified */ if (!address) { virReportError(VIR_ERR_XML_ERROR, _("%s: Missing required address attribute " "in route definition"), errorDetail); goto error; } if (!gateway) { virReportError(VIR_ERR_XML_ERROR, _("%s: Missing required gateway attribute " "in route definition"), errorDetail); goto error; } if (virSocketAddrParse(&def->address, address, AF_UNSPEC) < 0) { virReportError(VIR_ERR_XML_ERROR, _("%s: Bad network address '%s' " "in route definition"), errorDetail, address); goto error; } if (virSocketAddrParse(&def->gateway, gateway, AF_UNSPEC) < 0) { virReportError(VIR_ERR_XML_ERROR, _("%s: Bad gateway address '%s' " "in route definition"), errorDetail, gateway); goto error; } /* validate network address, etc. for each family */ if ((def->family == NULL) || (STREQ(def->family, "ipv4"))) { if (!(VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET) || VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_UNSPEC))) { virReportError(VIR_ERR_XML_ERROR, def->family == NULL ? _("%s: No family specified for non-IPv4 address '%s' " "in route definition") : _("%s: IPv4 family specified for non-IPv4 address '%s' " "in route definition"), errorDetail, address); goto error; } if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET)) { virReportError(VIR_ERR_XML_ERROR, def->family == NULL ? _("%s: No family specified for non-IPv4 gateway '%s' " "in route definition") : _("%s: IPv4 family specified for non-IPv4 gateway '%s' " "in route definition"), errorDetail, address); goto error; } if (netmask) { if (virSocketAddrParse(&def->netmask, netmask, AF_UNSPEC) < 0) { virReportError(VIR_ERR_XML_ERROR, _("%s: Bad netmask address '%s' " "in route definition"), errorDetail, netmask); goto error; } if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->netmask, AF_INET)) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid netmask '%s' " "for address '%s' (both must be IPv4)"), errorDetail, netmask, address); goto error; } if (def->has_prefix) { /* can't have both netmask and prefix at the same time */ virReportError(VIR_ERR_XML_ERROR, _("%s: Route definition cannot have both " "a prefix and a netmask"), errorDetail); goto error; } } if (def->prefix > 32) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid prefix %u specified " "in route definition, " "must be 0 - 32"), errorDetail, def->prefix); goto error; } } else if (STREQ(def->family, "ipv6")) { if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->address, AF_INET6)) { virReportError(VIR_ERR_XML_ERROR, _("%s: ipv6 family specified for non-IPv6 address '%s' " "in route definition"), errorDetail, address); goto error; } if (netmask) { virReportError(VIR_ERR_XML_ERROR, _("%s: Specifying netmask invalid for IPv6 address '%s' " "in route definition"), errorDetail, address); goto error; } if (!VIR_SOCKET_ADDR_IS_FAMILY(&def->gateway, AF_INET6)) { virReportError(VIR_ERR_XML_ERROR, _("%s: ipv6 specified for non-IPv6 gateway address '%s' " "in route definition"), errorDetail, gateway); goto error; } if (def->prefix > 128) { virReportError(VIR_ERR_XML_ERROR, _("%s: Invalid prefix %u specified " "in route definition, " "must be 0 - 128"), errorDetail, def->prefix); goto error; } } else { virReportError(VIR_ERR_XML_ERROR, _("%s: Unrecognized family '%s' " "in route definition"), errorDetail, def->family); goto error; } /* make sure the address is a network address */ if (netmask) { if (virSocketAddrMask(&def->address, &def->netmask, &testAddr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: Error converting address '%s' with netmask '%s' " "to network-address " "in route definition"), errorDetail, address, netmask); goto error; } } else { if (virSocketAddrMaskByPrefix(&def->address, def->prefix, &testAddr) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("%s: Error converting address '%s' with prefix %u " "to network-address " "in route definition"), errorDetail, address, def->prefix); goto error; } } if (!virSocketAddrEqual(&def->address, &testAddr)) { virReportError(VIR_ERR_XML_ERROR, _("%s: Address '%s' in route definition " "is not a network address"), errorDetail, address); goto error; } return def; error: virNetDevIPRouteFree(def); return NULL; }