[libvirt] [PATCHv2 01/13] New virSocketAddr utility functions

Laine Stump laine at laine.org
Wed Dec 22 18:58:00 UTC 2010


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




More information about the libvir-list mailing list