]> xenbits.xensource.com Git - libvirt.git/commitdiff
New virSocketAddr utility functions
authorLaine Stump <laine@laine.org>
Fri, 26 Nov 2010 18:51:44 +0000 (13:51 -0500)
committerLaine Stump <laine@laine.org>
Thu, 23 Dec 2010 20:52:11 +0000 (15:52 -0500)
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
src/util/network.c
src/util/network.h

index 0e3033dcb47775a585d9b62ed0a6fd705abfdb79..19841ef96a7a972d8f68d25020f4f79f860f671d 100644 (file)
@@ -559,6 +559,9 @@ virShrinkN;
 
 # network.h
 virSocketAddrIsNetmask;
+virSocketAddrMask;
+virSocketAddrMaskByPrefix;
+virSocketAddrPrefixToNetmask;
 virSocketCheckNetmask;
 virSocketFormatAddr;
 virSocketFormatAddrFull;
index 1abe78b821797993387043e63f45c50792c264f9..61044fc19dacaed305308163c83219c539837bfd 100644 (file)
@@ -287,6 +287,59 @@ int virSocketAddrIsNetmask(virSocketAddrPtr netmask) {
     return 0;
 }
 
+/**
+ * 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
@@ -486,3 +539,63 @@ 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);
+        }
+        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;
+}
index 521f466e2a3d0fc59fb015afaf658a0d7731eaa6..2fcee434d2d86d9837b01c107fc4cb9c316cb488 100644 (file)
@@ -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__ */