#include #include #include #include "pxe.h" #include "lwip/api.h" #include "lwip/dns.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, }; /* * parse the ip_str and return the ip address with *res. * return true if the whole string was consumed and the result * was valid. * */ static bool parse_dotquad(const char *ip_str, uint32_t *res) { const char *p = ip_str; uint8_t part = 0; uint32_t ip = 0; int i; for (i = 0; i < 4; i++) { while (is_digit(*p)) { part = part * 10 + *p - '0'; p++; } if (i != 3 && *p != '.') return false; ip = (ip << 8) | part; part = 0; p++; } p--; *res = htonl(ip); return *p == '\0'; } /* * Actual resolver function. * * Points to a null-terminated 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 */ __export uint32_t dns_resolv(const char *name) { err_t err; struct ip_addr ip; char fullname[512]; /* * Return failure on an empty input... this can happen during * some types of URL parsing, and this is the easiest place to * check for it. */ if (!name || !*name) return 0; /* If it is a valid dot quad, just return that value */ if (parse_dotquad(name, &ip.addr)) return ip.addr; /* Make sure we have at least one valid DNS server */ if (!dns_getserver(0).addr) return 0; /* Is it a local (unqualified) domain name? */ if (!strchr(name, '.') && LocalDomain[0]) { snprintf(fullname, sizeof fullname, "%s.%s", name, LocalDomain); name = fullname; } err = netconn_gethostbyname(name, &ip); if (err) return 0; return ip.addr; } /* * the one should be called from ASM file */ void pm_pxe_dns_resolv(com32sys_t *regs) { const char *name = MK_PTR(regs->ds, regs->esi.w[0]); regs->eax.l = dns_resolv(name); }