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 | } |
---|