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

Laine Stump laine at laine.org
Mon Dec 20 08:03:13 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
---
 src/libvirt_private.syms |    3 +
 src/util/network.c       |  130 ++++++++++++++++++++++++++++++++++++++++++++++
 src/util/network.h       |   10 ++++
 3 files changed, 143 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..e4791b9 100644
--- a/src/util/network.c
+++ b/src/util/network.c
@@ -288,6 +288,73 @@ 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 < 4; ii++)
+            addr->data.inet6.sin6_addr.s6_addr32[ii]
+                &= netmask->data.inet6.sin6_addr.s6_addr32[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, int prefix)
+{
+    virSocketAddr netmask;
+
+    if (virSocketAddrPrefixToNetmask(prefix, &netmask,
+                                     addr->data.stor.ss_family) < 0)
+        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 < 4; ii++)
+            addr->data.inet6.sin6_addr.s6_addr32[ii]
+                &= netmask.data.inet6.sin6_addr.s6_addr32[ii];
+        return 0;
+    }
+    return -1;
+}
+
+/**
  * virSocketCheckNetmask:
  * @addr1: a first network address
  * @addr2: a second network address
@@ -486,3 +553,66 @@ 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(int prefix,
+                                 virSocketAddrPtr netmask,
+                                 int family)
+{
+    int result = -1;
+
+    netmask->data.stor.ss_family = AF_UNSPEC; /* assume failure */
+
+    if (family == AF_INET) {
+        int ip = 0;
+
+        if (prefix < 0 || prefix > 32)
+            goto error;
+
+        while (prefix-- > 0) {
+            ip >>= 1;
+            ip |= 0x80000000;
+        }
+        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;
+        }
+        while (prefix-- > 0) {
+            /* final partial byte one bit at a time */
+            netmask->data.inet6.sin6_addr.s6_addr[ii] >>= 1;
+            netmask->data.inet6.sin6_addr.s6_addr[ii] |= 0x80;
+        }
+        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..6e1394f 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,
+                              int prefix);
 
 int virSocketGetNumNetmaskBits(const virSocketAddrPtr netmask);
+int virSocketAddrPrefixToNetmask(int prefix,
+                                 virSocketAddrPtr netmask,
+                                 int family);
 
 #endif /* __VIR_NETWORK_H__ */
-- 
1.7.3.4




More information about the libvir-list mailing list