diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fc53293ead..4cfa4ab4dc 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3269,6 +3269,7 @@ virSocketAddrCheckNetmask; virSocketAddrEqual; virSocketAddrFormat; virSocketAddrFormatFull; +virSocketAddrFormatWithPrefix; virSocketAddrGetIPPrefix; virSocketAddrGetNumNetmaskBits; virSocketAddrGetPath; diff --git a/src/util/viriptables.c b/src/util/viriptables.c index ac949efba7..78d979cfe8 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -353,37 +353,6 @@ iptablesRemoveUdpOutput(virFirewall *fw, } -static char *iptablesFormatNetwork(virSocketAddr *netaddr, - unsigned int prefix) -{ - virSocketAddr network; - g_autofree char *netstr = NULL; - 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; - - ret = g_strdup_printf("%s/%d", netstr, prefix); - - return ret; -} - - /* Allow all traffic coming from the bridge, with a valid network address * to proceed to WAN */ @@ -399,7 +368,7 @@ iptablesForwardAllowOut(virFirewall *fw, virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; - if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) + if (!(networkstr = virSocketAddrFormatWithPrefix(netaddr, prefix, true))) return -1; if (physdev && physdev[0]) @@ -487,7 +456,7 @@ iptablesForwardAllowRelatedIn(virFirewall *fw, VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; g_autofree char *networkstr = NULL; - if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) + if (!(networkstr = virSocketAddrFormatWithPrefix(netaddr, prefix, true))) return -1; if (physdev && physdev[0]) @@ -577,7 +546,7 @@ iptablesForwardAllowIn(virFirewall *fw, VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; g_autofree char *networkstr = NULL; - if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) + if (!(networkstr = virSocketAddrFormatWithPrefix(netaddr, prefix, true))) return -1; if (physdev && physdev[0]) @@ -829,7 +798,7 @@ iptablesForwardMasquerade(virFirewall *fw, virFirewallLayer layer = af == AF_INET ? VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; - if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) + if (!(networkstr = virSocketAddrFormatWithPrefix(netaddr, prefix, true))) return -1; if (VIR_SOCKET_ADDR_IS_FAMILY(&addr->start, af)) { @@ -972,7 +941,7 @@ iptablesForwardDontMasquerade(virFirewall *fw, virFirewallLayer layer = VIR_SOCKET_ADDR_FAMILY(netaddr) == AF_INET ? VIR_FIREWALL_LAYER_IPV4 : VIR_FIREWALL_LAYER_IPV6; - if (!(networkstr = iptablesFormatNetwork(netaddr, prefix))) + if (!(networkstr = virSocketAddrFormatWithPrefix(netaddr, prefix, true))) return -1; if (physdev && physdev[0]) diff --git a/src/util/virsocketaddr.c b/src/util/virsocketaddr.c index 94cbfc6264..430e43f2eb 100644 --- a/src/util/virsocketaddr.c +++ b/src/util/virsocketaddr.c @@ -511,6 +511,50 @@ virSocketAddrFormatFull(const virSocketAddr *addr, } +/* + * virSocketAddrFormatWithPrefix: + * @addr: an initialized virSocketAddr * + * @prefix: an IP network prefix (0-32 if IPv4, 0-128 if IPv6) + * @masked: true to mask off the host bits of the address + * + * Returns a string representation of the IP network described by + * @netaddr/@prefix. If @masked is true, the address is masked to + * remove the host bits according to prefix. So, for example, sending + * f(1.2.3.4, 24, true) would return "1.2.3.0/24", but f(1.2.3.4, 24, + * false) would return "1.2.3.4/24". + * + * returns false on failure (and logs an error message) + */ +char * +virSocketAddrFormatWithPrefix(virSocketAddr *addr, + unsigned int prefix, + bool masked) +{ + virSocketAddr network; + g_autofree char *netstr = NULL; + + if (!(VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET) || + VIR_SOCKET_ADDR_IS_FAMILY(addr, AF_INET6))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Only IPv4 or IPv6 addresses can be used with a prefix")); + return NULL; + } + + if (masked && virSocketAddrMaskByPrefix(addr, prefix, &network) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Failure to mask address")); + return NULL; + } + + netstr = virSocketAddrFormat(&network); + + if (!netstr) + return NULL; + + return g_strdup_printf("%s/%d", netstr, prefix); +} + + /* * virSocketAddrSetPort: * @addr: an initialized virSocketAddr * diff --git a/src/util/virsocketaddr.h b/src/util/virsocketaddr.h index f76e229730..ec265d6e44 100644 --- a/src/util/virsocketaddr.h +++ b/src/util/virsocketaddr.h @@ -88,6 +88,9 @@ char *virSocketAddrFormat(const virSocketAddr *addr); char *virSocketAddrFormatFull(const virSocketAddr *addr, bool withService, const char *separator); +char *virSocketAddrFormatWithPrefix(virSocketAddr *addr, + unsigned int prefix, + bool masked); char *virSocketAddrGetPath(virSocketAddr *addr);