summaryrefslogtreecommitdiffstats
path: root/contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c')
-rw-r--r--contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c349
1 files changed, 0 insertions, 349 deletions
diff --git a/contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c b/contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c
deleted file mode 100644
index 2b263fa..0000000
--- a/contrib/syslinux/syslinux-4.03/core/fs/pxe/dnsresolv.c
+++ /dev/null
@@ -1,349 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <core.h>
-#include "pxe.h"
-
-/* DNS CLASS values we care about */
-#define CLASS_IN 1
-
-/* DNS TYPE values we care about */
-#define TYPE_A 1
-#define TYPE_CNAME 5
-
-/*
- * The DNS header structure
- */
-struct dnshdr {
- uint16_t id;
- uint16_t flags;
- /* number of entries in the question section */
- uint16_t qdcount;
- /* number of resource records in the answer section */
- uint16_t ancount;
- /* number of name server resource records in the authority records section*/
- uint16_t nscount;
- /* number of resource records in the additional records section */
- uint16_t arcount;
-} __attribute__ ((packed));
-
-/*
- * The DNS query structure
- */
-struct dnsquery {
- uint16_t qtype;
- uint16_t qclass;
-} __attribute__ ((packed));
-
-/*
- * The DNS Resource recodes structure
- */
-struct dnsrr {
- uint16_t type;
- uint16_t class;
- uint32_t ttl;
- uint16_t rdlength; /* The lenght of this rr data */
- char rdata[];
-} __attribute__ ((packed));
-
-
-uint32_t dns_server[DNS_MAX_SERVERS] = {0, };
-
-
-/*
- * Turn a string in _src_ into a DNS "label set" in _dst_; returns the
- * number of dots encountered. On return, *dst is updated.
- */
-int dns_mangle(char **dst, const char *p)
-{
- char *q = *dst;
- char *count_ptr;
- char c;
- int dots = 0;
-
- count_ptr = q;
- *q++ = 0;
-
- while (1) {
- c = *p++;
- if (c == 0 || c == ':' || c == '/')
- break;
- if (c == '.') {
- dots++;
- count_ptr = q;
- *q++ = 0;
- continue;
- }
-
- *count_ptr += 1;
- *q++ = c;
- }
-
- if (*count_ptr)
- *q++ = 0;
-
- /* update the strings */
- *dst = q;
- 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;
- uint32_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;
-
- /* Make sure we have at least one valid DNS server */
- if (!dns_server[0])
- 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 */
- strcpy(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++;
- }
-
- 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;
- }
-
-done:
- free_port(local_port); /* Return port number to the free pool */
-
- return result;
-}
-
-
-/*
- * the one should be called from ASM file
- */
-void pxe_dns_resolv(com32sys_t *regs)
-{
- const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
-
- regs->eax.l = dns_resolv(name);
-}