[libvirt] [PATCH] 1/3 Add IPv4 and IPv6 parsing routines

Daniel Veillard veillard at redhat.com
Tue Oct 13 14:12:47 UTC 2009


    * src/util/util.h src/util/util.c: two new functions virParseIPv4
      and virParseIPv6

diff --git a/src/util/util.c b/src/util/util.c
index e5135fc..bbd29dc 100644
--- a/src/util/util.c
+++ b/src/util/util.c
@@ -1761,6 +1761,161 @@ void virGenerateMacAddr(const unsigned char *prefix,
     addr[5] = virRandom(256);
 }
 
+static int virParseIPv4Byte(const char **addr) {
+    unsigned int v;
+    const char *cur = *addr;
+
+    /* extend to accept hexa values ? */
+    if (cur == NULL)
+        return(-1);
+    if ((*cur < '0') || (*cur > '9'))
+        return(-1);
+    v = *cur++ - '0';
+    if ((*cur >= '0') && (*cur <= '9'))
+        v = 10 * v + *cur++ - '0';
+    if ((*cur >= '0') && (*cur <= '9'))
+        v = 10 * v + *cur++ - '0';
+    if (v > 255)
+        return(-1);
+    *addr = cur;
+    return(v);
+}
+
+/*
+ * virParseIPv4:
+ * @addr: pointer to the address string in classic dotted format and zero
+ *        terminated
+ * @res: optional pointer to the place to store the result
+ *
+ * Parse the IPv4 address in classic dot-decimal notation format like
+ * 192.0.2.235, and store the output if res is provided:
+ * for example res[0] = 192, res[1] = 0, res[2] = 2, res[3] = 235
+ *
+ * Retuns 0 in case of success and -1 in case of error
+ */
+int virParseIPv4(const char *addr, virIPv4Val *res) {
+    int v;
+    const char *cur = addr;
+
+    if (addr == NULL)
+        return(-1);
+
+    if (res)
+        memset(res, 0, sizeof(*res));
+
+    v = virParseIPv4Byte(&cur);
+    if ((v < 0) || (*cur != '.'))
+        return(-1);
+    if (res) (*res)[0] = (unsigned char) v;
+    cur++;
+
+    v = virParseIPv4Byte(&cur);
+    if ((v < 0) || (*cur != '.'))
+        return(-1);
+    if (res) (*res)[1] = (unsigned char) v;
+    cur++;
+
+    v = virParseIPv4Byte(&cur);
+    if ((v < 0) || (*cur != '.'))
+        return(-1);
+    if (res) (*res)[2] = (unsigned char) v;
+    cur++;
+
+    v = virParseIPv4Byte(&cur);
+    if ((v < 0) || (*cur != 0))
+        return(-1);
+    if (res) (*res)[3] = (unsigned char) v;
+
+    return(0);
+}
+
+static int virParseIPv6Short(const char **addr) {
+    const char *cur = *addr;
+    char *end_ptr;
+    unsigned long result;
+
+    if (cur == NULL)
+        return(-1);
+    errno = 0;
+
+    /* This is solely to avoid accepting the leading
+     * space or "+" that strtoul would otherwise accept.
+     */
+    if (!c_isxdigit(*cur))
+        return(-1);
+
+    result = strtoul(cur, &end_ptr, 16);
+
+    if (((end_ptr - cur) < 1) || ((end_ptr - cur) > 4) ||
+        (errno != 0) || (result > 0xFFFF))
+        return(-1);
+
+    *addr = end_ptr;
+    return((int) result);
+}
+
+static int virCountColumn(const char *cur) {
+    int ret;
+
+    for (ret = 0;*cur != 0;cur++)
+         if (*cur == ':') ret++;
+    return(ret);
+}
+
+/*
+ * virParseIPv6:
+ * @addr: pointer to the address string in classic hex and column format
+ *        and zero terminated
+ * @res: optional pointer to the place to store the result
+ *
+ * Parse the IPv6 address in classic dot-decimal notation format like
+ * 2001:db8:85a3:0:0:8a2e:370:7334, and store the output if res is provided:
+ * for example res[0] = 0x2001, res[1] = 0xdb8, etc.
+ * TODO: doesn't support the :: compression notation yet
+ *
+ * Retuns 0 in case of success and -1 in case of error
+ */
+int virParseIPv6(const char *addr, virIPv6Val *res) {
+    int v, i, left, compact;
+    const char *cur = addr;
+
+    if (addr == NULL)
+        return(-1);
+
+    if (res)
+        memset(res, 0, sizeof(*res));
+
+    compact = 0;
+    for (i = 0;i < 8;i++) {
+        if ((*cur == ':') && (compact == 0)) {
+            compact = 1;
+            cur++;
+            if (i == 0) {
+                /* if leading we expect :: */
+                if (*cur != ':')
+                    return(-1);
+                cur++;
+                if (*cur == 0)
+                    return(0);
+            }
+            left = virCountColumn(cur);
+            if (7 - left <= i)
+                return(-1);
+            i = 7 - left;
+        }
+        v = virParseIPv6Short(&cur);
+        if (v < 0)
+            return(-1);
+        if (((i < 7) && (*cur != ':')) ||
+            ((i == 7) && (*cur != 0)))
+            return(-1);
+        if (res)
+           (*res)[i] = (unsigned short) v;
+        cur++;
+    }
+
+    return(0);
+}
 
 int virEnumFromString(const char *const*types,
                       unsigned int ntypes,
diff --git a/src/util/util.h b/src/util/util.h
index 8679636..b1be46f 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -185,6 +185,12 @@ void virFormatMacAddr(const unsigned char *addr,
 void virGenerateMacAddr(const unsigned char *prefix,
                         unsigned char *addr);
 
+typedef unsigned char virIPv4Val[4];
+typedef unsigned short virIPv6Val[8];
+
+int virParseIPv4(const char *addr, virIPv4Val *res);
+int virParseIPv6(const char *addr, virIPv6Val *res);
+
 int virDiskNameToIndex(const char* str);
 
 

-- 
Daniel Veillard      | libxml Gnome XML XSLT toolkit  http://xmlsoft.org/
daniel at veillard.com  | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library  http://libvirt.org/




More information about the libvir-list mailing list