aboutsummaryrefslogtreecommitdiff
path: root/core/fs/pxe/dnsresolv.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/fs/pxe/dnsresolv.c')
-rw-r--r--core/fs/pxe/dnsresolv.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/core/fs/pxe/dnsresolv.c b/core/fs/pxe/dnsresolv.c
new file mode 100644
index 0000000..afb9e21
--- /dev/null
+++ b/core/fs/pxe/dnsresolv.c
@@ -0,0 +1,134 @@
+#include <stdio.h>
+#include <string.h>
+#include <core.h>
+#include "pxe.h"
+#include "lwip/api.h"
+#include "lwip/dns.h"
+
+/* DNS CLASS values we care about */
+#define CLASS_IN 1
+
+/* DNS TYPE values we care about */
+#define TYPE_A 1
+#define TYPE_CNAME 5
+
+/*
+ * The DNS header structure
+ */
+struct dnshdr {
+ uint16_t id;
+ uint16_t flags;
+ /* number of entries in the question section */
+ uint16_t qdcount;
+ /* number of resource records in the answer section */
+ uint16_t ancount;
+ /* number of name server resource records in the authority records section*/
+ uint16_t nscount;
+ /* number of resource records in the additional records section */
+ uint16_t arcount;
+} __attribute__ ((packed));
+
+/*
+ * The DNS query structure
+ */
+struct dnsquery {
+ uint16_t qtype;
+ uint16_t qclass;
+} __attribute__ ((packed));
+
+/*
+ * The DNS Resource recodes structure
+ */
+struct dnsrr {
+ uint16_t type;
+ uint16_t class;
+ uint32_t ttl;
+ uint16_t rdlength; /* The lenght of this rr data */
+ char rdata[];
+} __attribute__ ((packed));
+
+
+uint32_t dns_server[DNS_MAX_SERVERS] = {0, };
+
+/*
+ * parse the ip_str and return the ip address with *res.
+ * return true if the whole string was consumed and the result
+ * was valid.
+ *
+ */
+static bool parse_dotquad(const char *ip_str, uint32_t *res)
+{
+ const char *p = ip_str;
+ uint8_t part = 0;
+ uint32_t ip = 0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ while (is_digit(*p)) {
+ part = part * 10 + *p - '0';
+ p++;
+ }
+ if (i != 3 && *p != '.')
+ return false;
+
+ ip = (ip << 8) | part;
+ part = 0;
+ p++;
+ }
+ p--;
+
+ *res = htonl(ip);
+ return *p == '\0';
+}
+
+/*
+ * Actual resolver function.
+ *
+ * Points to a null-terminated in _name_ and returns the ip addr in
+ * _ip_ if it exists and can be found. If _ip_ = 0 on exit, the
+ * lookup failed. _name_ will be updated
+ */
+__export uint32_t dns_resolv(const char *name)
+{
+ err_t err;
+ struct ip_addr ip;
+ char fullname[512];
+
+ /*
+ * Return failure on an empty input... this can happen during
+ * some types of URL parsing, and this is the easiest place to
+ * check for it.
+ */
+ if (!name || !*name)
+ return 0;
+
+ /* If it is a valid dot quad, just return that value */
+ if (parse_dotquad(name, &ip.addr))
+ return ip.addr;
+
+ /* Make sure we have at least one valid DNS server */
+ if (!dns_getserver(0).addr)
+ return 0;
+
+ /* Is it a local (unqualified) domain name? */
+ if (!strchr(name, '.') && LocalDomain[0]) {
+ snprintf(fullname, sizeof fullname, "%s.%s", name, LocalDomain);
+ name = fullname;
+ }
+
+ err = netconn_gethostbyname(name, &ip);
+ if (err)
+ return 0;
+
+ return ip.addr;
+}
+
+/*
+ * the one should be called from ASM file
+ */
+void pm_pxe_dns_resolv(com32sys_t *regs)
+{
+ const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
+
+ regs->eax.l = dns_resolv(name);
+}