static void dns_servers(void *data, int opt_len)
{
- int num = opt_len >> 2;
- int i;
+ const uint32_t *dp = data;
+ int num = 0;
- if (num > DNS_MAX_SERVERS)
- num = DNS_MAX_SERVERS;
+ while (num < DNS_MAX_SERVERS) {
+ uint32_t ip;
- for (i = 0; i < num; i++) {
- dns_server[i] = *(uint32_t *)data;
- data += 4;
- }
+ if (opt_len < 4)
+ break;
-#if 0
- /*
- * if you find you got no corret DNS server, you can add
- * it here manually. BUT be carefull the DNS_MAX_SERVERS
- */
- if (i < DNS_MAX_SERVERS ) {
- dns_server[i++] = your_master_dns_server;
- dns_server[i++] = your_second_dns_server;
+ opt_len -= 4;
+ ip = *dp++;
+ if (ip_ok(ip))
+ dns_server[num++] = ip;
}
-#endif
+ while (num < DNS_MAX_SERVERS)
+ dns_server[num++] = 0;
}
static void local_domain(void *data, int opt_len)
char *p = (char *)data + opt_len;
char *ld = LocalDomain;
char end = *p;
-
+
*p = '\0'; /* Zero-terminate option */
dns_mangle(&ld, data);
*p = end; /* Restore ending byte */
if (opt_len != 4)
return;
-
+
if (IPInfo.serverip)
return;
-
+
ip = *(uint32_t *)data;
if (ip_ok(ip))
IPInfo.serverip = ip;
static void client_identifier(void *data, int opt_len)
{
if (opt_len > MAC_MAX || opt_len < 2 ||
- MAC_len != (opt_len >> 8) ||
+ MAC_len != (opt_len >> 8) ||
*(uint8_t *)data != MAC_type)
return;
strncpy(boot_file, data, opt_len);
boot_file[opt_len] = 0;
}
-
+
static void uuid_client_identifier(void *data, int opt_len)
{
int type = *(uint8_t *)data;
{
if ((opt_len && 0xff) != 4)
return ;
-
+
RebootTime = ntohl(*(uint32_t *)data);
DHCPMagic |= 8; /* Got reboot time */
}
void (*fun) (void *, int);
};
-static struct dhcp_options dhcp_opts[] = {
+static struct dhcp_options dhcp_opts[] = {
{1, subnet_mask},
{3, router},
{6, dns_servers},
};
/*
- * Parse a sequence of DHCP options, pointed to by _option_;
+ * Parse a sequence of DHCP options, pointed to by _option_;
* -- some DHCP servers leave option fields unterminated
* in violation of the spec.
*
* filter contains the minimum value for the option to recognize
* -- this is used to restrict parsing to PXELINUX-specific options only.
- */
+ */
static void parse_dhcp_options(void *option, int size, uint8_t opt_filter)
{
uint8_t opt_num;
int i = 0;
char *p = option;
struct dhcp_options *opt;
-
+
while (size--) {
opt_num = *p++;
continue;
if (opt_num == 0xff)
break;
-
+
/* Anything else will have a lenght filed */
opt_len = *p++; /* c <- option lenght */
size = size - opt_len - 1;
if (opt_num == opt->opt_num) {
opt->fun(p, opt_len);
break;
- }
+ }
opt ++;
}
-
+
/* parse next */
p += opt_len;
}
}
-
+
/*
* parse_dhcp
*
over_load = 0;
if (ip_ok(dhcp->yip))
IPInfo.myip = dhcp->yip;
-
+
if (ip_ok(dhcp->sip))
IPInfo.serverip = dhcp->sip;
-
+
opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options;
- if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC))
+ if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC))
parse_dhcp_options(&dhcp->options, opt_len, 0);
- if (over_load & 1)
+ if (over_load & 1)
parse_dhcp_options(&dhcp->bootfile, 128, 0);
- else if (dhcp->bootfile[0])
+ else if (dhcp->bootfile[0])
strcpy(boot_file, dhcp->bootfile);
-
- if (over_load & 2)
+
+ if (over_load & 2)
parse_dhcp_options(dhcp->sname, 64, 0);
-}
+}
} __attribute__ ((packed));
/*
- * The DNS Resource recodes structure
+ * The DNS Resource recodes structure
*/
struct dnsrr {
uint16_t type;
/*
- * Turn a string in _src_ into a DNS "label set" in _dst_; returns the
+ * 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;
+ int dots = 0;
count_ptr = q;
*q++ = 0;
while (1) {
c = *p++;
- if (c == 0 || c == ':')
+ if (c == 0 || c == ':' || c == '/')
break;
if (c == '.') {
dots++;
*q++ = 0;
continue;
}
-
+
*count_ptr += 1;
*q++ = c;
}
*dst = q;
return dots;
}
-
+
/*
* Compare two sets of DNS labels, in _s1_ and _s2_; the one in _s2_
uint8_t *q = dst;
const uint8_t *p = src;
unsigned int c0, c1;
-
+
while (1) {
c0 = p[0];
if (c0 >= 0xc0) {
static char *dns_skiplabel(char *label)
{
uint8_t c;
-
+
while (1) {
c = *label++;
if (c >= 0xc0)
const uint8_t *timeout_ptr = TimeoutTable;
uint32_t oldtime;
uint32_t srv;
- uint32_t *srv_ptr = dns_server;
+ uint32_t *srv_ptr;
struct dnshdr *hd1 = (struct dnshdr *)DNSSendBuf;
- struct dnshdr *hd2 = (struct dnshdr *)DNSRecvBuf;
+ 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;
+ 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();
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);
+ 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++;
- while (srv_ptr < dns_server + DNS_MAX_SERVERS) {
- srv = *srv_ptr++;
- if (!srv)
- continue; /* just move on before runing the time out */
+ 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.buffer_size = p - DNSSendBuf;
udp_write.buffer = FAR_PTR(DNSSendBuf);
err = pxe_call(PXENV_UDP_WRITE, &udp_write);
- if (err || udp_write.status != 0)
+ if (err || udp_write.status)
continue;
-
+
oldtime = jiffies();
while (1) {
udp_read.status = 0;
udp_read.dest_ip = IPInfo.myip;
udp_read.s_port = DNS_PORT;
udp_read.d_port = local_port;
- udp_read.buffer_size = DNS_MAX_PACKET;
+ udp_read.buffer_size = PKTBUF_SIZE;
udp_read.buffer = FAR_PTR(DNSRecvBuf);
err = pxe_call(PXENV_UDP_READ, &udp_read);
if (err || udp_read.status)
continue;
-
+
/* Got a packet, deal with it... */
if (hd2->id == hd1->id)
break;
- if (jiffies()-oldtime >= timeout) {
- /* time out */
- timeout = *timeout_ptr++;
- if (!timeout)
- goto done; /* All time ticks run out */
- else
- goto again;
- }
+ if (jiffies() - oldtime >= timeout)
+ goto again;
}
if ((hd2->flags ^ 0x80) & htons(0xf80f))
- goto badness;
+ goto badness;
ques = htons(hd2->qdcount); /* Questions */
reps = htons(hd2->ancount); /* Replies */
default:
break;
}
- }
+ }
/* not the one we want, try next */
p += sizeof(struct dnsrr) + rd_len;
; 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))
+ if (hd2->flags == htons(0x480))
continue;
break; /* failed */
return result;
}
-
-
+
+
/*
- * the one should be called from ASM file
+ * the one should be called from ASM file
*/
void pxe_dns_resolv(com32sys_t *regs)
{