• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
parse_dotquad(const char * ip_str,uint32_t * res)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  */
dns_resolv(const char * name)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  */
pm_pxe_dns_resolv(com32sys_t * regs)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