[syslinux:lwip] core pxe: Use the lwip dns resolver

syslinux-bot for Eric W. Biederman ebiederm at xmission.com
Fri Apr 22 20:05:55 PDT 2011


Commit-ID:  0290be0cbaae619892c91def3cd13c54614a9dbb
Gitweb:     http://syslinux.zytor.com/commit/0290be0cbaae619892c91def3cd13c54614a9dbb
Author:     Eric W. Biederman <ebiederm at xmission.com>
AuthorDate: Sun, 10 Apr 2011 05:29:12 -0700
Committer:  Eric W. Biederman <ebiederm at xmission.com>
CommitDate: Tue, 12 Apr 2011 14:40:54 -0700

core pxe: Use the lwip dns resolver

When we start receiving packets at the undi layer we can
no longer use the the pxe udp layer.  So make our lives
simple by using the lwip dns resolve which which works
without changes and seems to be a little more comprehensive.

Signed-off-by: Eric W. Biederman <ebiederm at xmission.com>


---
 core/fs/pxe/dnsresolv.c |  252 ++++-------------------------------------------
 1 files changed, 19 insertions(+), 233 deletions(-)

diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
index 06d5a73..b827edb 100644
--- a/core/fs/pxe/dnsresolv.c
+++ b/core/fs/pxe/dnsresolv.c
@@ -2,6 +2,8 @@
 #include <string.h>
 #include <core.h>
 #include "pxe.h"
+#include "lwip/api.h"
+#include "lwip/dns.h"
 
 /* DNS CLASS values we care about */
 #define CLASS_IN	1
@@ -86,255 +88,39 @@ int dns_mangle(char **dst, const char *p)
     return dots;
 }
 
-
-/*
- * Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s2_
- * is allowed pointers relative to a packet in buf.
- *
- */
-static bool dns_compare(const void *s1, const void *s2, const void *buf)
-{
-    const uint8_t *q = s1;
-    const uint8_t *p = s2;
-    unsigned int c0, c1;
-
-    while (1) {
-	c0 = p[0];
-        if (c0 >= 0xc0) {
-	    /* Follow pointer */
-	    c1 = p[1];
-	    p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1;
-	} else if (c0) {
-	    c0++;		/* Include the length byte */
-	    if (memcmp(q, p, c0))
-		return false;
-	    q += c0;
-	    p += c0;
-	} else {
-	    return *q == 0;
-	}
-    }
-}
-
-/*
- * Copy a DNS label into a buffer, considering the possibility that we might
- * have to follow pointers relative to "buf".
- * Returns a pointer to the first free byte *after* the terminal null.
- */
-static void *dns_copylabel(void *dst, const void *src, const void *buf)
-{
-    uint8_t *q = dst;
-    const uint8_t *p = src;
-    unsigned int c0, c1;
-
-    while (1) {
-	c0 = p[0];
-        if (c0 >= 0xc0) {
-	    /* Follow pointer */
-	    c1 = p[1];
-	    p = (const uint8_t *)buf + ((c0 - 0xc0) << 8) + c1;
-	} else if (c0) {
-	    c0++;		/* Include the length byte */
-	    memcpy(q, p, c0);
-	    p += c0;
-	    q += c0;
-	} else {
-	    *q++ = 0;
-	    return q;
-	}
-    }
-}
-
-/*
- * Skip past a DNS label set in DS:SI
- */
-static char *dns_skiplabel(char *label)
-{
-    uint8_t c;
-
-    while (1) {
-        c = *label++;
-        if (c >= 0xc0)
-            return ++label; /* pointer is two bytes */
-        if (c == 0)
-            return label;
-        label += c;
-    }
-}
-
 /*
  * Actual resolver function
  * Points to a null-terminated or :-terminated string in _name_
  * and returns the ip addr in _ip_ if it exists and can be found.
  * If _ip_ = 0 on exit, the lookup failed. _name_ will be updated
- *
- * XXX: probably need some caching here.
  */
 uint32_t dns_resolv(const char *name)
 {
-    static char __lowmem DNSSendBuf[PKTBUF_SIZE];
-    static char __lowmem DNSRecvBuf[PKTBUF_SIZE];
-    char *p;
-    int err;
-    int dots;
-    int same;
-    int rd_len;
-    int ques, reps;    /* number of questions and replies */
-    uint8_t timeout;
-    const uint8_t *timeout_ptr = TimeoutTable;
-    jiffies_t oldtime;
-    uint32_t srv;
-    uint32_t *srv_ptr;
-    struct dnshdr *hd1 = (struct dnshdr *)DNSSendBuf;
-    struct dnshdr *hd2 = (struct dnshdr *)DNSRecvBuf;
-    struct dnsquery *query;
-    struct dnsrr *rr;
-    static __lowmem struct s_PXENV_UDP_WRITE udp_write;
-    static __lowmem struct s_PXENV_UDP_READ  udp_read;
-    uint16_t local_port;
-    uint32_t result = 0;
+    err_t err;
+    struct ip_addr ip;
+    char dns_name[PKTBUF_SIZE];
+    const char *src;
+    char *dst;
 
     /* Make sure we have at least one valid DNS server */
-    if (!dns_server[0])
+    if (!dns_getserver(0).addr)
 	return 0;
 
-    /* Get a local port number */
-    local_port = get_port();
-
-    /* First, fill the DNS header struct */
-    hd1->id++;                      /* New query ID */
-    hd1->flags   = htons(0x0100);   /* Recursion requested */
-    hd1->qdcount = htons(1);        /* One question */
-    hd1->ancount = 0;               /* No answers */
-    hd1->nscount = 0;               /* No NS */
-    hd1->arcount = 0;               /* No AR */
-
-    p = DNSSendBuf + sizeof(struct dnshdr);
-    dots = dns_mangle(&p, name);   /* store the CNAME */
-
-    if (!dots) {
-        p--; /* Remove final null */
-        /* Uncompressed DNS label set so it ends in null */
-        p = stpcpy(p, LocalDomain);
-    }
-
-    /* Fill the DNS query packet */
-    query = (struct dnsquery *)p;
-    query->qtype  = htons(TYPE_A);
-    query->qclass = htons(CLASS_IN);
-    p += sizeof(struct dnsquery);
-
-    /* Now send it to name server */
-    timeout_ptr = TimeoutTable;
-    timeout = *timeout_ptr++;
-    srv_ptr = dns_server;
-    while (timeout) {
-	srv = *srv_ptr++;
-	if (!srv) {
-	    srv_ptr = dns_server;
-	    srv = *srv_ptr++;
+    /* Copy the name to look up to ensure it is null terminated */
+    for (dst = dns_name, src = name; *src; src++, dst++) {
+	int ch = *src;
+	if (ch == '\0' || ch == ':' || ch == '/') {
+	    *dst = '\0';
+	    break;
 	}
-
-        udp_write.status      = 0;
-        udp_write.ip          = srv;
-        udp_write.gw          = gateway(srv);
-        udp_write.src_port    = local_port;
-        udp_write.dst_port    = DNS_PORT;
-        udp_write.buffer_size = p - DNSSendBuf;
-        udp_write.buffer      = FAR_PTR(DNSSendBuf);
-        err = pxe_call(PXENV_UDP_WRITE, &udp_write);
-        if (err || udp_write.status)
-            continue;
-
-        oldtime = jiffies();
-	do {
-	    if (jiffies() - oldtime >= timeout)
-		goto again;
-
-            udp_read.status      = 0;
-            udp_read.src_ip      = srv;
-            udp_read.dest_ip     = IPInfo.myip;
-            udp_read.s_port      = DNS_PORT;
-            udp_read.d_port      = local_port;
-            udp_read.buffer_size = PKTBUF_SIZE;
-            udp_read.buffer      = FAR_PTR(DNSRecvBuf);
-            err = pxe_call(PXENV_UDP_READ, &udp_read);
-	} while (err || udp_read.status || hd2->id != hd1->id);
-
-        if ((hd2->flags ^ 0x80) & htons(0xf80f))
-            goto badness;
-
-        ques = htons(hd2->qdcount);   /* Questions */
-        reps = htons(hd2->ancount);   /* Replies   */
-        p = DNSRecvBuf + sizeof(struct dnshdr);
-        while (ques--) {
-            p = dns_skiplabel(p); /* Skip name */
-            p += 4;               /* Skip question trailer */
-        }
-
-        /* Parse the replies */
-        while (reps--) {
-            same = dns_compare(DNSSendBuf + sizeof(struct dnshdr),
-			       p, DNSRecvBuf);
-            p = dns_skiplabel(p);
-            rr = (struct dnsrr *)p;
-            rd_len = ntohs(rr->rdlength);
-            if (same && ntohs(rr->class) == CLASS_IN) {
-		switch (ntohs(rr->type)) {
-		case TYPE_A:
-		    if (rd_len == 4) {
-			result = *(uint32_t *)rr->rdata;
-			goto done;
-		    }
-		    break;
-		case TYPE_CNAME:
-		    dns_copylabel(DNSSendBuf + sizeof(struct dnshdr),
-				  rr->rdata, DNSRecvBuf);
-		    /*
-		     * We should probably rescan the packet from the top
-		     * here, and technically we might have to send a whole
-		     * new request here...
-		     */
-		    break;
-		default:
-		    break;
-		}
-	    }
-
-            /* not the one we want, try next */
-            p += sizeof(struct dnsrr) + rd_len;
-        }
-
-    badness:
-        /*
-         *
-         ; We got back no data from this server.
-         ; Unfortunately, for a recursive, non-authoritative
-         ; query there is no such thing as an NXDOMAIN reply,
-         ; which technically means we can't draw any
-         ; conclusions.  However, in practice that means the
-         ; domain doesn't exist.  If this turns out to be a
-         ; problem, we may want to add code to go through all
-         ; the servers before giving up.
-
-         ; If the DNS server wasn't capable of recursion, and
-         ; isn't capable of giving us an authoritative reply
-         ; (i.e. neither AA or RA set), then at least try a
-         ; different setver...
-        */
-        if (hd2->flags == htons(0x480))
-            continue;
-
-        break; /* failed */
-
-    again:
-	continue;
+	*dst = ch;
     }
 
-done:
-    free_port(local_port);	/* Return port number to the free pool */
+    err = netconn_gethostbyname(dns_name, &ip);
+    if (err)
+	return 0;
 
-    return result;
+    return ip.addr;
 }
 
 



More information about the Syslinux-commits mailing list