Home | History | Annotate | Download | only in pxe
      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