]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dns] Pass a non-null peer socket address to xfer_open_socket() master
authorMichael Brown <mcb30@ipxe.org>
Tue, 21 Jul 2026 12:28:23 +0000 (13:28 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 21 Jul 2026 12:35:25 +0000 (13:35 +0100)
Commit 3662065 ("[dns] Use all configured DNS servers") changed the
logic from opening a single defined nameserver address to opening an
unspecified peer socket address and then specifying the full peer
address for each transmitted packet.

The peer socket address was left unspecified by passing a null pointer
to xfer_open_socket().  This is supported by the UDP socket opener,
but technically violates the internal API (which allows the local
socket address to be a null pointer, but not the peer socket address).
In particular, in a debug build using DEBUG=open, the debug code will
itself dereference the peer address pointer.

Fix by embedding the name server socket address within the DNS request
structure, and passing this to xfer_open_socket().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/udp/dns.c

index 3f534b99f7c2f1f78e92839d0a53384b06509c1b..3f53675f9e7b18ef6bc7b0862b2baacd7c8e0368 100644 (file)
@@ -466,6 +466,13 @@ struct dns_request {
                struct sockaddr_in sin;
                struct sockaddr_in6 sin6;
        } address;
+       /** Current name server address */
+       union {
+               struct sockaddr sa;
+               struct sockaddr_tcpip st;
+               struct sockaddr_in sin;
+               struct sockaddr_in6 sin6;
+       } nameserver;
        /** Initial query type */
        uint16_t qtype;
        /** Buffer for current query */
@@ -587,12 +594,6 @@ static int dns_question ( struct dns_request *dns ) {
  */
 static int dns_send_packet ( struct dns_request *dns ) {
        struct dns_header *query = &dns->buf.query;
-       union {
-               struct sockaddr sa;
-               struct sockaddr_tcpip st;
-               struct sockaddr_in sin;
-               struct sockaddr_in6 sin6;
-       } nameserver;
        struct xfer_metadata meta;
        unsigned int index;
 
@@ -600,25 +601,25 @@ static int dns_send_packet ( struct dns_request *dns ) {
        start_timer ( &dns->timer );
 
        /* Construct DNS server address */
-       memset ( &nameserver, 0, sizeof ( nameserver ) );
-       nameserver.st.st_port = htons ( DNS_PORT );
+       memset ( &dns->nameserver, 0, sizeof ( dns->nameserver ) );
+       dns->nameserver.st.st_port = htons ( DNS_PORT );
        if ( ! dns_count ) {
                DBGC ( dns, "DNS %p lost DNS servers mid query\n", dns );
                return -EINVAL;
        }
        index = ( dns->index % dns_count );
        if ( index < dns6.count ) {
-               nameserver.sin6.sin6_family = AF_INET6;
-               memcpy ( &nameserver.sin6.sin6_addr, &dns6.in6[index],
-                        sizeof ( nameserver.sin6.sin6_addr ) );
+               dns->nameserver.sin6.sin6_family = AF_INET6;
+               memcpy ( &dns->nameserver.sin6.sin6_addr, &dns6.in6[index],
+                        sizeof ( dns->nameserver.sin6.sin6_addr ) );
        } else {
-               nameserver.sin.sin_family = AF_INET;
-               nameserver.sin.sin_addr = dns4.in[index - dns6.count];
+               dns->nameserver.sin.sin_family = AF_INET;
+               dns->nameserver.sin.sin_addr = dns4.in[index - dns6.count];
        }
 
        /* Construct metadata */
        memset ( &meta, 0, sizeof ( meta ) );
-       meta.dest = &nameserver.sa;
+       meta.dest = &dns->nameserver.sa;
 
        /* Generate query identifier if applicable */
        if ( ! query->id )
@@ -626,7 +627,7 @@ static int dns_send_packet ( struct dns_request *dns ) {
 
        /* Send query */
        DBGC ( dns, "DNS %p sending %s query ID %#04x for %s type %s\n", dns,
-              sock_ntoa ( &nameserver.sa ), ntohs ( query->id ),
+              sock_ntoa ( &dns->nameserver.sa ), ntohs ( query->id ),
               dns_name ( &dns->name ), dns_type ( dns->question->qtype ) );
 
        /* Send the data */
@@ -1030,7 +1031,7 @@ static int dns_resolv ( struct interface *resolv,
 
        /* Open UDP connection */
        if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
-                                      NULL, NULL ) ) != 0 ) {
+                                      &dns->nameserver.sa, NULL ) ) != 0 ) {
                DBGC ( dns, "DNS %p could not open socket: %s\n",
                       dns, strerror ( rc ) );
                goto err_open_socket;