[dns] Handle AAAA records
authorMatthew Iselin <matthew@theiselins.net>
Thu, 2 Jun 2011 13:14:57 +0000 (23:14 +1000)
committerMarty Connor <mdc@etherboot.org>
Thu, 21 Jul 2011 00:55:19 +0000 (20:55 -0400)
Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/include/gpxe/dns.h
src/net/udp/dns.c

index 9e5e874..49eb7a3 100644 (file)
@@ -19,6 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #define DNS_TYPE_A             1
 #define DNS_TYPE_CNAME         5
+#define DNS_TYPE_AAAA          28
 #define DNS_TYPE_ANY           255
 
 #define DNS_CLASS_IN           1
@@ -78,6 +79,11 @@ struct dns_rr_info_a {
        struct in_addr in_addr;
 } __attribute__ (( packed ));
 
+struct dns_rr_info_aaaa {
+       struct dns_rr_info_common common;
+       struct in6_addr in6_addr;
+} __attribute__ (( packed ));
+
 struct dns_rr_info_cname {
        struct dns_rr_info_common common;
        char cname[0];
@@ -86,6 +92,7 @@ struct dns_rr_info_cname {
 union dns_rr_info {
        struct dns_rr_info_common common;
        struct dns_rr_info_a a;
+       struct dns_rr_info_aaaa aaaa;
        struct dns_rr_info_cname cname;
 };
 
index c7bb6aa..cf513bf 100644 (file)
@@ -334,6 +334,7 @@ static int dns_xfer_deliver_raw ( struct xfer_interface *socket,
        const struct dns_header *reply = data;
        union dns_rr_info *rr_info;
        struct sockaddr_in *sin;
+       struct sockaddr_in6 *sin6;
        unsigned int qtype = dns->qinfo->qtype;
 
        /* Sanity check */
@@ -399,6 +400,19 @@ static int dns_xfer_deliver_raw ( struct xfer_interface *socket,
                                return 0;
                        }
                        break;
+               
+               case htons ( DNS_TYPE_AAAA ):
+
+                       /* Found the target AAAA record */
+                       DBGC ( dns, "DNS %p found address %s\n",
+                              dns, inet6_ntoa ( rr_info->aaaa.in6_addr ) );
+                       sin6 = ( struct sockaddr_in6 * ) &dns->sa;
+                       sin6->sin_family = AF_INET6;
+                       sin6->sin6_addr = rr_info->aaaa.in6_addr;
+
+                       /* Mark operation as complete */
+                       dns_done ( dns, 0 );
+                       return 0;
 
                default:
                        DBGC ( dns, "DNS %p got unknown record type %d\n",
@@ -414,19 +428,28 @@ static int dns_xfer_deliver_raw ( struct xfer_interface *socket,
 
        case htons ( DNS_TYPE_A ):
                /* We asked for an A record and got nothing;
+                * try the AAAA record.
+                */
+               DBGC ( dns, "DNS %p found no A record; trying AAAA\n", dns );
+               dns->qinfo->qtype = htons ( DNS_TYPE_AAAA );
+               dns_send_packet ( dns );
+               return 0;
+
+       case htons ( DNS_TYPE_AAAA ):
+               /* We asked for an AAAA record and got nothing;
                 * try the CNAME.
                 */
-               DBGC ( dns, "DNS %p found no A record; trying CNAME\n", dns );
+               DBGC ( dns, "DNS %p found no AAAA record; trying CNAME\n", dns );
                dns->qinfo->qtype = htons ( DNS_TYPE_CNAME );
                dns_send_packet ( dns );
                return 0;
 
        case htons ( DNS_TYPE_CNAME ):
                /* We asked for a CNAME record.  If we got a response
-                * (i.e. if the next A query is already set up), then
+                * (i.e. if the next AAAA query is already set up), then
                 * issue it, otherwise abort.
                 */
-               if ( dns->qinfo->qtype == htons ( DNS_TYPE_A ) ) {
+               if ( dns->qinfo->qtype == htons ( DNS_TYPE_AAAA ) ) {
                        dns_send_packet ( dns );
                        return 0;
                } else {