changeset 3265:0c5c5e876391

ngx_inet6_addr()
author Igor Sysoev <igor@sysoev.ru>
date Mon, 02 Nov 2009 12:50:00 +0000
parents ebcee0063cd8
children 798141791ad3
files src/core/ngx_inet.c src/core/ngx_inet.h
diffstat 2 files changed, 123 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -59,6 +59,126 @@ ngx_inet_addr(u_char *text, size_t len)
 }
 
 
+#if (NGX_HAVE_INET6)
+
+ngx_int_t
+ngx_inet6_addr(u_char *p, size_t len, u_char *addr)
+{
+    u_char      c, *zero, *digit, *s, *d;
+    size_t      len4;
+    ngx_uint_t  n, nibbles, word;
+
+    if (len == 0) {
+        return NGX_ERROR;
+    }
+
+    zero = NULL;
+    digit = NULL;
+    len4 = 0;
+    nibbles = 0;
+    word = 0;
+    n = 8;
+
+    if (p[0] == ':') {
+        p++;
+        len--;
+    }
+
+    for (/* void */; len; len--) {
+        c = *p++;
+
+        if (c == ':') {
+            if (nibbles) {
+                digit = p;
+                len4 = len;
+                *addr++ = (u_char) (word >> 8);
+                *addr++ = (u_char) (word & 0xff);
+
+                if (--n) {
+                    nibbles = 0;
+                    word = 0;
+                    continue;
+                }
+
+            } else {
+                if (zero == NULL) {
+                    digit = p;
+                    len4 = len;
+                    zero = addr;
+                    continue;
+                }
+            }
+
+            return NGX_ERROR;
+        }
+
+        if (c == '.' && nibbles) {
+            if (n < 2) {
+                return NGX_ERROR;
+            }
+
+            word = ngx_inet_addr(digit, len4 - 1);
+            if (word == INADDR_NONE) {
+                return NGX_ERROR;
+            }
+
+            word = ntohl(word);
+            *addr++ = (u_char) ((word >> 24) & 0xff);
+            *addr++ = (u_char) ((word >> 16) & 0xff);
+            n--;
+            break;
+        }
+
+        if (++nibbles > 4) {
+            return NGX_ERROR;
+        }
+
+        if (c >= '0' && c <= '9') {
+            word = word * 16 + (c - '0');
+            continue;
+        }
+
+        c |= 0x20;
+
+        if (c >= 'a' && c <= 'f') {
+            word = word * 16 + (c - 'a') + 10;
+            continue;
+        }
+
+        return NGX_ERROR;
+    }
+
+    if (nibbles == 0 && zero == NULL) {
+        return NGX_ERROR;
+    }
+
+    *addr++ = (u_char) (word >> 8);
+    *addr++ = (u_char) (word & 0xff);
+
+    if (--n) {
+        if (zero) {
+            n *= 2;
+            s = addr - 1;
+            d = s + n;
+            while (s >= zero) {
+                *d-- = *s--;
+            }
+            ngx_memzero(zero, n);
+            return NGX_OK;
+        }
+
+    } else {
+        if (zero == NULL) {
+            return NGX_OK;
+        }
+    }
+
+    return NGX_ERROR;
+}
+
+#endif
+
+
 size_t
 ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len, ngx_uint_t port)
 {
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -102,6 +102,9 @@ typedef struct {
 
 
 in_addr_t ngx_inet_addr(u_char *text, size_t len);
+#if (NGX_HAVE_INET6)
+ngx_int_t ngx_inet6_addr(u_char *p, size_t len, u_char *addr);
+#endif
 size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len,
     ngx_uint_t port);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);