1 #include <stdio.h> 2 #include <string.h> 3 #include <core.h> 4 #include "pxe.h" 5 #include "lwip/api.h" 6 #include "lwip/dns.h" 7 8 /* DNS CLASS values we care about */ 9 #define CLASS_IN 1 10 11 /* DNS TYPE values we care about */ 12 #define TYPE_A 1 13 #define TYPE_CNAME 5 14 15 /* 16 * The DNS header structure 17 */ 18 struct dnshdr { 19 uint16_t id; 20 uint16_t flags; 21 /* number of entries in the question section */ 22 uint16_t qdcount; 23 /* number of resource records in the answer section */ 24 uint16_t ancount; 25 /* number of name server resource records in the authority records section*/ 26 uint16_t nscount; 27 /* number of resource records in the additional records section */ 28 uint16_t arcount; 29 } __attribute__ ((packed)); 30 31 /* 32 * The DNS query structure 33 */ 34 struct dnsquery { 35 uint16_t qtype; 36 uint16_t qclass; 37 } __attribute__ ((packed)); 38 39 /* 40 * The DNS Resource recodes structure 41 */ 42 struct dnsrr { 43 uint16_t type; 44 uint16_t class; 45 uint32_t ttl; 46 uint16_t rdlength; /* The lenght of this rr data */ 47 char rdata[]; 48 } __attribute__ ((packed)); 49 50 51 uint32_t dns_server[DNS_MAX_SERVERS] = {0, }; 52 53 /* 54 * parse the ip_str and return the ip address with *res. 55 * return true if the whole string was consumed and the result 56 * was valid. 57 * 58 */ 59 static bool parse_dotquad(const char *ip_str, uint32_t *res) 60 { 61 const char *p = ip_str; 62 uint8_t part = 0; 63 uint32_t ip = 0; 64 int i; 65 66 for (i = 0; i < 4; i++) { 67 while (is_digit(*p)) { 68 part = part * 10 + *p - '0'; 69 p++; 70 } 71 if (i != 3 && *p != '.') 72 return false; 73 74 ip = (ip << 8) | part; 75 part = 0; 76 p++; 77 } 78 p--; 79 80 *res = htonl(ip); 81 return *p == '\0'; 82 } 83 84 /* 85 * Actual resolver function. 86 * 87 * Points to a null-terminated in _name_ and returns the ip addr in 88 * _ip_ if it exists and can be found. If _ip_ = 0 on exit, the 89 * lookup failed. _name_ will be updated 90 */ 91 __export uint32_t dns_resolv(const char *name) 92 { 93 err_t err; 94 struct ip_addr ip; 95 char fullname[512]; 96 97 /* 98 * Return failure on an empty input... this can happen during 99 * some types of URL parsing, and this is the easiest place to 100 * check for it. 101 */ 102 if (!name || !*name) 103 return 0; 104 105 /* If it is a valid dot quad, just return that value */ 106 if (parse_dotquad(name, &ip.addr)) 107 return ip.addr; 108 109 /* Make sure we have at least one valid DNS server */ 110 if (!dns_getserver(0).addr) 111 return 0; 112 113 /* Is it a local (unqualified) domain name? */ 114 if (!strchr(name, '.') && LocalDomain[0]) { 115 snprintf(fullname, sizeof fullname, "%s.%s", name, LocalDomain); 116 name = fullname; 117 } 118 119 err = netconn_gethostbyname(name, &ip); 120 if (err) 121 return 0; 122 123 return ip.addr; 124 } 125 126 /* 127 * the one should be called from ASM file 128 */ 129 void pm_pxe_dns_resolv(com32sys_t *regs) 130 { 131 const char *name = MK_PTR(regs->ds, regs->esi.w[0]); 132 133 regs->eax.l = dns_resolv(name); 134 } 135