virSocketPrefixToNetmask: Given a 'prefix', which is the number of 1
bits in a netmask, fill in a virSocketAddr object with a netmask as an
IP address (IPv6 or IPv4).
virSocketAddrMask: Mask off the host bits in one virSocketAddr
according to the netmask in another virSocketAddr.
virSocketAddrMaskByPrefix, Mask off the host bits in a virSocketAddr
according to a prefix (number of 1 bits in netmask).
VIR_SOCKET_FAMILY: return the family of a virSocketAddr
---
V2 changes:
* Simplify virSocketAddrMaskByPrefix by calling virSocketAddrMask instead
of duplicating code.
* do bitwise operations arithmetically rather than in loops
* prefix is now unsigned when it is a function arg.
src/libvirt_private.syms | 3 +
src/util/network.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++
src/util/network.h | 10 ++++
3 files changed, 127 insertions(+), 0 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0e3033d..19841ef 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -559,6 +559,9 @@ virShrinkN;
# network.h
virSocketAddrIsNetmask;
+virSocketAddrMask;
+virSocketAddrMaskByPrefix;
+virSocketAddrPrefixToNetmask;
virSocketCheckNetmask;
virSocketFormatAddr;
virSocketFormatAddrFull;
diff --git a/src/util/network.c b/src/util/network.c
index 1abe78b..12b56ea 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -288,6 +288,59 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask) {
}
/**
+ * virSocketAddrMask:
+ * @addr: address that needs to be masked
+ * @netmask: the netmask address
+ *
+ * Mask off the host bits of @addr according to @netmask, turning it
+ * into a network address.
+ *
+ * Returns 0 in case of success, or -1 on error.
+ */
+int
+virSocketAddrMask(virSocketAddrPtr addr, const virSocketAddrPtr netmask)
+{
+ if (addr->data.stor.ss_family != netmask->data.stor.ss_family)
+ return -1;
+
+ if (addr->data.stor.ss_family == AF_INET) {
+ addr->data.inet4.sin_addr.s_addr
+ &= netmask->data.inet4.sin_addr.s_addr;
+ return 0;
+ }
+ if (addr->data.stor.ss_family == AF_INET6) {
+ int ii;
+ for (ii = 0; ii < 16; ii++)
+ addr->data.inet6.sin6_addr.s6_addr[ii]
+ &= netmask->data.inet6.sin6_addr.s6_addr[ii];
+ return 0;
+ }
+ return -1;
+}
+
+/**
+ * virSocketAddrMaskByPrefix:
+ * @addr: address that needs to be masked
+ * @prefix: prefix (# of 1 bits) of netmask to apply
+ *
+ * Mask off the host bits of @addr according to @prefix, turning it
+ * into a network address.
+ *
+ * Returns 0 in case of success, or -1 on error.
+ */
+int
+virSocketAddrMaskByPrefix(virSocketAddrPtr addr, unsigned int prefix)
+{
+ virSocketAddr netmask;
+
+ if (virSocketAddrPrefixToNetmask(prefix, &netmask,
+ addr->data.stor.ss_family) < 0)
+ return -1;
+
+ return virSocketAddrMask(addr, &netmask);
+}
+
+/**
* virSocketCheckNetmask:
* @addr1: a first network address
* @addr2: a second network address
@@ -486,3 +539,64 @@ int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask)
}
return -1;
}
+
+/**
+ * virSocketPrefixToNetmask:
+ * @prefix: number of 1 bits to put in the netmask
+ * @netmask: address to fill in with the desired netmask
+ * @family: family of the address (AF_INET or AF_INET6 only)
+ *
+ * given @prefix and @family, fill in @netmask with a netmask
+ * (eg 255.255.255.0).
+ *
+ * Returns 0 on success or -1 on error.
+ */
+
+int
+virSocketAddrPrefixToNetmask(unsigned int prefix,
+ virSocketAddrPtr netmask,
+ int family)
+{
+ int result = -1;
+
+ netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */
+
+ if (family == AF_INET) {
+ int ip;
+
+ if (prefix > 32)
+ goto error;
+
+ ip = prefix ? ~((1 << (32 - prefix)) - 1) : 0;
+ netmask->data.inet4.sin_addr.s_addr = htonl(ip);
+ netmask->data.stor.ss_family = AF_INET;
+ result = 0;
+
+ } else if (family == AF_INET6) {
+ int ii = 0;
+
+ if (prefix > 128)
+ goto error;
+
+ while (prefix >= 8) {
+ /* do as much as possible an entire byte at a time */
+ netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0xff;
+ prefix -= 8;
+ }
+ if (prefix > 0) {
+ /* final partial byte */
+ netmask->data.inet6.sin6_addr.s6_addr[ii++]
+ = ~((1 << (8 - prefix)) -1);
+ }
+ ii++;
+ while (ii < 16) {
+ /* zerofill remainder in case it wasn't initialized */
+ netmask->data.inet6.sin6_addr.s6_addr[ii++] = 0;
+ }
+ netmask->data.stor.ss_family = AF_INET6;
+ result = 0;
+ }
+
+error:
+ return result;
+}
diff --git a/src/util/network.h b/src/util/network.h
index 521f466..2fcee43 100644
--- a/src/util/network.h
+++ b/src/util/network.h
@@ -41,6 +41,9 @@ typedef struct {
# define VIR_SOCKET_IS_FAMILY(s, f) \
((s)->data.sa.sa_family == f)
+# define VIR_SOCKET_FAMILY(s) \
+ ((s)->data.sa.sa_family)
+
typedef virSocketAddr *virSocketAddrPtr;
int virSocketParseAddr (const char *val,
@@ -70,7 +73,14 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask);
int virSocketCheckNetmask (virSocketAddrPtr addr1,
virSocketAddrPtr addr2,
virSocketAddrPtr netmask);
+int virSocketAddrMask (virSocketAddrPtr addr,
+ const virSocketAddrPtr netmask);
+int virSocketAddrMaskByPrefix(virSocketAddrPtr addr,
+ unsigned int prefix);
int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask);
+int virSocketAddrPrefixToNetmask(unsigned int prefix,
+ virSocketAddrPtr netmask,
+ int family);
#endif /* __VIR_NETWORK_H__ */
--
1.7.3.4