[ipv6] Implement inet6_aton, numeric IPv6 address resolution
authorMatthew Iselin <matthew@theiselins.net>
Thu, 26 May 2011 11:27:14 +0000 (21:27 +1000)
committerMarty Connor <mdc@etherboot.org>
Tue, 19 Jul 2011 01:21:25 +0000 (21:21 -0400)
Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/core/resolv.c
src/net/ipv6.c

index 7167482..02fe312 100644 (file)
@@ -116,6 +116,7 @@ static int numeric_resolv ( struct resolv_interface *resolv,
                            const char *name, struct sockaddr *sa ) {
        struct numeric_resolv *numeric;
        struct sockaddr_in *sin;
                            const char *name, struct sockaddr *sa ) {
        struct numeric_resolv *numeric;
        struct sockaddr_in *sin;
+       struct sockaddr_in6 *sin6;
 
        /* Allocate and initialise structure */
        numeric = zalloc ( sizeof ( *numeric ) );
 
        /* Allocate and initialise structure */
        numeric = zalloc ( sizeof ( *numeric ) );
@@ -132,8 +133,13 @@ static int numeric_resolv ( struct resolv_interface *resolv,
        /* Attempt to resolve name */
        sin = ( ( struct sockaddr_in * ) &numeric->sa );
        sin->sin_family = AF_INET;
        /* Attempt to resolve name */
        sin = ( ( struct sockaddr_in * ) &numeric->sa );
        sin->sin_family = AF_INET;
-       if ( inet_aton ( name, &sin->sin_addr ) == 0 )
-               numeric->rc = -EINVAL;
+       if ( inet_aton ( name, &sin->sin_addr ) == 0 ) {
+               sin6 = ( ( struct sockaddr_in6 * ) &numeric->sa );
+               sin6->sin_family = AF_INET6;
+               if ( inet6_aton ( name, &sin6->sin6_addr ) == 0 ) {
+                       numeric->rc = -EINVAL;
+               }
+       }
 
        /* Attach to parent interface, mortalise self, and return */
        resolv_plug_plug ( &numeric->resolv, resolv );
 
        /* Attach to parent interface, mortalise self, and return */
        resolv_plug_plug ( &numeric->resolv, resolv );
index 9925435..abf5353 100644 (file)
@@ -431,6 +431,50 @@ char * inet6_ntoa ( struct in6_addr in6 ) {
        return buf;
 }
 
        return buf;
 }
 
+/**
+ * Convert a string to an IPv6 address.
+ *
+ * @v in6   String to convert to an address.
+ */
+int inet6_aton ( const char *cp, struct in6_addr *inp ) {
+       char convbuf[40];
+       char *tmp = convbuf, *next = convbuf;
+       size_t i = 0;
+       
+       strcpy ( convbuf, cp );
+       
+       DBG ( "ipv6 converting %s to an in6_addr\n", cp );
+       
+       /* Handle the first part of the address (or all of it if no zero-compression. */
+       while ( ( next = strchr ( next, ':' ) ) ) {
+               /* Cater for zero-compression. */
+               if ( *tmp == ':' )
+                       break;
+               
+               /* Convert to integer. */
+               inp->s6_addr16[i++] = htons( strtoul ( tmp, 0, 16 ) );
+               
+               *next++ = 0;
+               tmp = next;
+       }
+       
+       /* Handle zero-compression now (go backwards). */
+       i = 7;
+       if ( *tmp == ':' ) {
+               next = strrchr ( next, ':' );
+               do
+               {
+                       tmp = next + 1;
+                       *next-- = 0;
+               
+                       /* Convert to integer. */
+                       inp->s6_addr16[i--] = htons( strtoul ( tmp, 0, 16 ) );
+               } while ( ( next = strrchr ( next, ':' ) ) );
+       }
+       
+       return 1;
+}
+
 static const char * ipv6_ntoa ( const void *net_addr ) {
        return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) );
 }
 static const char * ipv6_ntoa ( const void *net_addr ) {
        return inet6_ntoa ( * ( ( struct in6_addr * ) net_addr ) );
 }