1243 lines
37 KiB
Diff
1243 lines
37 KiB
Diff
From: Tias Guns <tias@ulyssis.org>
|
|
Date: Tue, 20 Mar 2012 23:10:18 +0000
|
|
Subject: [PATCH] fix nslookup, add libres, a dietlibc resolver
|
|
|
|
patches from 'dietlibc-resolver' by Dan Drown
|
|
"""
|
|
use the bionic's resolver functions do not allow changing the dns
|
|
server. Use
|
|
dietlibc's resolver code instead (see package libres-devel)
|
|
"""
|
|
http://dan.drown.org/android/src/busybox/
|
|
|
|
libres from 'libres-0.32-1' also by Dan Drown:
|
|
http://dan.drown.org/android/src/libres/
|
|
---
|
|
Makefile | 1 +
|
|
libres/Kbuild.src | 11 +++
|
|
libres/Makefile | 32 ++++++++
|
|
libres/README | 5 ++
|
|
libres/dietdns.h | 189 +++++++++++++++++++++++++++++++++++++++++++++
|
|
libres/dn_expand.c | 12 +++
|
|
libres/dnscruft.c | 119 ++++++++++++++++++++++++++++
|
|
libres/dnscruft2.c | 132 +++++++++++++++++++++++++++++++
|
|
libres/dnscruft3.c | 6 ++
|
|
libres/freeaddrinfo.c | 14 ++++
|
|
libres/gai_strerror.c | 14 ++++
|
|
libres/getaddrinfo.c | 137 ++++++++++++++++++++++++++++++++
|
|
libres/gethostbyname2_r.c | 35 +++++++++
|
|
libres/h_errno.c | 1 +
|
|
libres/res_init.c | 12 +++
|
|
libres/res_mkquery.c | 85 ++++++++++++++++++++
|
|
libres/res_query.c | 81 +++++++++++++++++++
|
|
libres/test.c | 105 +++++++++++++++++++++++++
|
|
networking/nslookup.c | 25 +++---
|
|
19 files changed, 1005 insertions(+), 11 deletions(-)
|
|
create mode 100644 libres/Kbuild.src
|
|
create mode 100644 libres/Makefile
|
|
create mode 100644 libres/README
|
|
create mode 100644 libres/dietdns.h
|
|
create mode 100644 libres/dn_expand.c
|
|
create mode 100644 libres/dnscruft.c
|
|
create mode 100644 libres/dnscruft2.c
|
|
create mode 100644 libres/dnscruft3.c
|
|
create mode 100644 libres/freeaddrinfo.c
|
|
create mode 100644 libres/gai_strerror.c
|
|
create mode 100644 libres/getaddrinfo.c
|
|
create mode 100644 libres/gethostbyname2_r.c
|
|
create mode 100644 libres/h_errno.c
|
|
create mode 100644 libres/res_init.c
|
|
create mode 100644 libres/res_mkquery.c
|
|
create mode 100644 libres/res_query.c
|
|
create mode 100644 libres/test.c
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index c31ca89..8e0226a 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -476,6 +476,7 @@ libs-y := \
|
|
init/ \
|
|
libbb/ \
|
|
libpwdgrp/ \
|
|
+ libres/ \
|
|
loginutils/ \
|
|
mailutils/ \
|
|
miscutils/ \
|
|
diff --git a/libres/Kbuild.src b/libres/Kbuild.src
|
|
new file mode 100644
|
|
index 0000000..abd4194
|
|
--- /dev/null
|
|
+++ b/libres/Kbuild.src
|
|
@@ -0,0 +1,11 @@
|
|
+# Makefile for busybox
|
|
+#
|
|
+# Copyright (C) 2012-2012 by Tias Guns <tias@ulyssis.org>
|
|
+#
|
|
+# Licensed under GPLv2, see file LICENSE in this source tree.
|
|
+
|
|
+lib-$(CONFIG_NSLOOKUP) += getaddrinfo.o gethostbyname2_r.o freeaddrinfo.o
|
|
+lib-$(CONFIG_NSLOOKUP) += dnscruft.o dnscruft2.o dnscruft3.o
|
|
+lib-$(CONFIG_NSLOOKUP) += res_init.o res_query.o res_mkquery.o
|
|
+lib-$(CONFIG_NSLOOKUP) += h_errno.o gai_strerror.o
|
|
+lib-$(CONFIG_NSLOOKUP) += dn_expand.o
|
|
diff --git a/libres/Makefile b/libres/Makefile
|
|
new file mode 100644
|
|
index 0000000..4a56888
|
|
--- /dev/null
|
|
+++ b/libres/Makefile
|
|
@@ -0,0 +1,32 @@
|
|
+CC=agcc
|
|
+
|
|
+OBJECTS=getaddrinfo.o
|
|
+OBJECTS+=gethostbyname2_r.o
|
|
+OBJECTS+=dnscruft.o
|
|
+OBJECTS+=dnscruft2.o
|
|
+OBJECTS+=dnscruft3.o
|
|
+OBJECTS+=h_errno.o
|
|
+OBJECTS+=res_query.o
|
|
+OBJECTS+=res_mkquery.o
|
|
+OBJECTS+=gai_strerror.o
|
|
+OBJECTS+=freeaddrinfo.o
|
|
+OBJECTS+=res_init.o
|
|
+OBJECTS+=dn_expand.o
|
|
+
|
|
+CFLAGS+=-Wall
|
|
+
|
|
+all: libres.a test
|
|
+clean:
|
|
+ rm -f $(OBJECTS) libres.a test.o test
|
|
+
|
|
+test: libres.a test.o
|
|
+ $(CC) $(CFLAGS) -o test test.o libres.a
|
|
+
|
|
+libres.a: $(OBJECTS)
|
|
+ ar r libres.a $(OBJECTS)
|
|
+ ranlib libres.a
|
|
+
|
|
+.PHONY: all clean
|
|
+
|
|
+%.o: %.c dietdns.h
|
|
+ $(CC) $(CFLAGS) -c $<
|
|
diff --git a/libres/README b/libres/README
|
|
new file mode 100644
|
|
index 0000000..cab8e47
|
|
--- /dev/null
|
|
+++ b/libres/README
|
|
@@ -0,0 +1,5 @@
|
|
+all these files are from dietlibc, modified to fit as a plug-in resolver
|
|
+
|
|
+Work by Dan Drown, called libres-0.32-1
|
|
+available at:
|
|
+http://dan.drown.org/android/src/libres/
|
|
diff --git a/libres/dietdns.h b/libres/dietdns.h
|
|
new file mode 100644
|
|
index 0000000..9ae0b4d
|
|
--- /dev/null
|
|
+++ b/libres/dietdns.h
|
|
@@ -0,0 +1,189 @@
|
|
+#ifndef __DIETDNS_H_
|
|
+#define __DIETDNS_H_
|
|
+
|
|
+#define DIET_MAXDNAME 1025 /* maximum domain name */
|
|
+#define DIET_PACKETSZ 512
|
|
+
|
|
+#define DIET_MAXNS 8 /* max # name servers we'll track */
|
|
+#define DIET_MAXDNSRCH 6 /* max # domains in search path */
|
|
+#define DIET_MAXRESOLVSORT 10 /* number of net to sort on */
|
|
+
|
|
+struct diet_res_state {
|
|
+ int retrans; /* retransmission time interval */
|
|
+ int retry; /* number of times to retransmit */
|
|
+ unsigned long options; /* option flags - see below. */
|
|
+ int nscount; /* number of name servers */
|
|
+ struct sockaddr_in
|
|
+ nsaddr_list[DIET_MAXNS]; /* address of name server */
|
|
+#define nsaddr nsaddr_list[0] /* for backward compatibility */
|
|
+ unsigned short id; /* current message id */
|
|
+ char *dnsrch[DIET_MAXDNSRCH+1]; /* components of domain to search */
|
|
+ char defdname[256]; /* default domain (deprecated) */
|
|
+ unsigned long pfcode; /* RES_PRF_ flags - see below. */
|
|
+ unsigned ndots:4; /* threshold for initial abs. query */
|
|
+ unsigned nsort:4; /* number of elements in sort_list[] */
|
|
+ char unused[3];
|
|
+ struct {
|
|
+ struct in_addr addr;
|
|
+ uint32_t mask;
|
|
+ } sort_list[DIET_MAXRESOLVSORT];
|
|
+ char pad[72];
|
|
+};
|
|
+
|
|
+/*
|
|
+ * Values for class field
|
|
+ */
|
|
+enum diet_ns_class {
|
|
+ diet_ns_c_invalid = 0, /* Cookie. */
|
|
+ diet_ns_c_in = 1, /* Internet. */
|
|
+ diet_ns_c_2 = 2, /* unallocated/unsupported. */
|
|
+ diet_ns_c_chaos = 3, /* MIT Chaos-net. */
|
|
+ diet_ns_c_hs = 4, /* MIT Hesiod. */
|
|
+ /* Query class values which do not appear in resource records */
|
|
+ diet_ns_c_none = 254, /* for prereq. sections in update requests */
|
|
+ diet_ns_c_any = 255, /* Wildcard match. */
|
|
+ diet_ns_c_max = 65536
|
|
+};
|
|
+
|
|
+#define DIET_C_IN diet_ns_c_in
|
|
+
|
|
+/*
|
|
+ * Currently defined opcodes.
|
|
+ */
|
|
+enum diet_ns_opcode {
|
|
+ diet_ns_o_query = 0, /* Standard query. */
|
|
+ diet_ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */
|
|
+ diet_ns_o_status = 2, /* Name server status query (unsupported). */
|
|
+ /* Opcode 3 is undefined/reserved. */
|
|
+ diet_ns_o_notify = 4, /* Zone change notification. */
|
|
+ diet_ns_o_update = 5, /* Zone update message. */
|
|
+ diet_ns_o_max = 6
|
|
+};
|
|
+
|
|
+#define DIET_QUERY diet_ns_o_query
|
|
+
|
|
+/*
|
|
+ * Currently defined type values for resources and queries.
|
|
+ */
|
|
+enum diet_ns_type {
|
|
+ diet_ns_t_invalid = 0, /* Cookie. */
|
|
+ diet_ns_t_a = 1, /* Host address. */
|
|
+ diet_ns_t_ns = 2, /* Authoritative server. */
|
|
+ diet_ns_t_md = 3, /* Mail destination. */
|
|
+ diet_ns_t_mf = 4, /* Mail forwarder. */
|
|
+ diet_ns_t_cname = 5, /* Canonical name. */
|
|
+ diet_ns_t_soa = 6, /* Start of authority zone. */
|
|
+ diet_ns_t_mb = 7, /* Mailbox domain name. */
|
|
+ diet_ns_t_mg = 8, /* Mail group member. */
|
|
+ diet_ns_t_mr = 9, /* Mail rename name. */
|
|
+ diet_ns_t_null = 10, /* Null resource record. */
|
|
+ diet_ns_t_wks = 11, /* Well known service. */
|
|
+ diet_ns_t_ptr = 12, /* Domain name pointer. */
|
|
+ diet_ns_t_hinfo = 13, /* Host information. */
|
|
+ diet_ns_t_minfo = 14, /* Mailbox information. */
|
|
+ diet_ns_t_mx = 15, /* Mail routing information. */
|
|
+ diet_ns_t_txt = 16, /* Text strings. */
|
|
+ diet_ns_t_rp = 17, /* Responsible person. */
|
|
+ diet_ns_t_afsdb = 18, /* AFS cell database. */
|
|
+ diet_ns_t_x25 = 19, /* X_25 calling address. */
|
|
+ diet_ns_t_isdn = 20, /* ISDN calling address. */
|
|
+ diet_ns_t_rt = 21, /* Router. */
|
|
+ diet_ns_t_nsap = 22, /* NSAP address. */
|
|
+ diet_ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */
|
|
+ diet_ns_t_sig = 24, /* Security signature. */
|
|
+ diet_ns_t_key = 25, /* Security key. */
|
|
+ diet_ns_t_px = 26, /* X.400 mail mapping. */
|
|
+ diet_ns_t_gpos = 27, /* Geographical position (withdrawn). */
|
|
+ diet_ns_t_aaaa = 28, /* Ip6 Address. */
|
|
+ diet_ns_t_loc = 29, /* Location Information. */
|
|
+ diet_ns_t_nxt = 30, /* Next domain (security). */
|
|
+ diet_ns_t_eid = 31, /* Endpoint identifier. */
|
|
+ diet_ns_t_nimloc = 32, /* Nimrod Locator. */
|
|
+ diet_ns_t_srv = 33, /* Server Selection. */
|
|
+ diet_ns_t_atma = 34, /* ATM Address */
|
|
+ diet_ns_t_naptr = 35, /* Naming Authority PoinTeR */
|
|
+ diet_ns_t_kx = 36, /* Key Exchange */
|
|
+ diet_ns_t_cert = 37, /* Certification record */
|
|
+ diet_ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */
|
|
+ diet_ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
|
|
+ diet_ns_t_sink = 40, /* Kitchen sink (experimentatl) */
|
|
+ diet_ns_t_opt = 41, /* EDNS0 option (meta-RR) */
|
|
+ diet_ns_t_tsig = 250, /* Transaction signature. */
|
|
+ diet_ns_t_ixfr = 251, /* Incremental zone transfer. */
|
|
+ diet_ns_t_axfr = 252, /* Transfer zone of authority. */
|
|
+ diet_ns_t_mailb = 253, /* Transfer mailbox records. */
|
|
+ diet_ns_t_maila = 254, /* Transfer mail agent records. */
|
|
+ diet_ns_t_any = 255, /* Wildcard match. */
|
|
+ diet_ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
|
|
+ diet_ns_t_max = 65536
|
|
+};
|
|
+
|
|
+#define DIET_T_A diet_ns_t_a
|
|
+#define DIET_T_NS diet_ns_t_ns
|
|
+#define DIET_T_CNAME diet_ns_t_cname
|
|
+#define DIET_T_SOA diet_ns_t_soa
|
|
+#define DIET_T_PTR diet_ns_t_ptr
|
|
+#define DIET_T_MX diet_ns_t_mx
|
|
+#define DIET_T_TXT diet_ns_t_txt
|
|
+#define DIET_T_AAAA diet_ns_t_aaaa
|
|
+#define DIET_T_ANY diet_ns_t_any
|
|
+
|
|
+/*
|
|
+ * Currently defined response codes.
|
|
+ */
|
|
+enum diet_ns_rcode {
|
|
+ diet_ns_r_noerror = 0, /* No error occurred. */
|
|
+ diet_ns_r_formerr = 1, /* Format error. */
|
|
+ diet_ns_r_servfail = 2, /* Server failure. */
|
|
+ diet_ns_r_nxdomain = 3, /* Name error. */
|
|
+ diet_ns_r_notimpl = 4, /* Unimplemented. */
|
|
+ diet_ns_r_refused = 5, /* Operation refused. */
|
|
+ /* these are for BIND_UPDATE */
|
|
+ diet_ns_r_yxdomain = 6, /* Name exists */
|
|
+ diet_ns_r_yxrrset = 7, /* RRset exists */
|
|
+ diet_ns_r_nxrrset = 8, /* RRset does not exist */
|
|
+ diet_ns_r_notauth = 9, /* Not authoritative for zone */
|
|
+ diet_ns_r_notzone = 10, /* Zone of record different from zone section */
|
|
+ diet_ns_r_max = 11,
|
|
+ /* The following are TSIG extended errors */
|
|
+ diet_ns_r_badsig = 16,
|
|
+ diet_ns_r_badkey = 17,
|
|
+ diet_ns_r_badtime = 18
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+#define DIET_NOERROR diet_ns_r_noerror
|
|
+#define DIET_FORMERR diet_ns_r_formerr
|
|
+#define DIET_SERVFAIL diet_ns_r_servfail
|
|
+#define DIET_NXDOMAIN diet_ns_r_nxdomain
|
|
+#define DIET_NOTIMP diet_ns_r_notimpl
|
|
+#define DIET_REFUSED diet_ns_r_refused
|
|
+#define DIET_YXDOMAIN diet_ns_r_yxdomain
|
|
+#define DIET_YXRRSET diet_ns_r_yxrrset
|
|
+#define DIET_NXRRSET diet_ns_r_nxrrset
|
|
+#define DIET_NOTAUTH diet_ns_r_notauth
|
|
+#define DIET_NOTZONE diet_ns_r_notzone
|
|
+
|
|
+
|
|
+#define DIET_RES_RECURSE 0x00000040 /* recursion desired */
|
|
+
|
|
+extern struct diet_res_state _diet_res;
|
|
+extern int diet_h_errno;
|
|
+
|
|
+int __dns_gethostbyx_r(const char* name, struct hostent* result,
|
|
+ char *buf, size_t buflen,
|
|
+ struct hostent **RESULT, int *h_errnop, int lookfor);
|
|
+int diet_gethostbyname2_r(const char* name, int AF, struct hostent* result,
|
|
+ char *buf, size_t buflen,
|
|
+ struct hostent **RESULT, int *h_errnop);
|
|
+int diet_res_query(const char *dname, int class, int type, unsigned char *answer, int anslen);
|
|
+int diet_res_mkquery(int op, const char *dname, int class, int type, char* data,
|
|
+ int datalen, const unsigned char* newrr, char* buf, int buflen);
|
|
+const char* diet_gai_strerror(int error);
|
|
+int diet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
|
|
+void diet_freeaddrinfo(struct addrinfo *res);
|
|
+int diet_res_init(void);
|
|
+int diet_dn_expand(const unsigned char *msg, const unsigned char *eomorig, const unsigned char *comp_dn, unsigned char *exp_dn, int length);
|
|
+
|
|
+#endif
|
|
diff --git a/libres/dn_expand.c b/libres/dn_expand.c
|
|
new file mode 100644
|
|
index 0000000..9eb4587
|
|
--- /dev/null
|
|
+++ b/libres/dn_expand.c
|
|
@@ -0,0 +1,12 @@
|
|
+#include <netinet/in.h>
|
|
+#include <arpa/nameser.h>
|
|
+#include <resolv.h>
|
|
+#include <netdb.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+extern int __dns_decodename(const unsigned char *packet,unsigned int ofs,unsigned char *dest,
|
|
+ unsigned int maxlen,const unsigned char* behindpacket);
|
|
+
|
|
+int diet_dn_expand(const unsigned char *msg, const unsigned char *eomorig, const unsigned char *comp_dn, unsigned char *exp_dn, int length) {
|
|
+ return __dns_decodename(msg,comp_dn-msg,exp_dn,length,eomorig)-(comp_dn-msg);
|
|
+}
|
|
diff --git a/libres/dnscruft.c b/libres/dnscruft.c
|
|
new file mode 100644
|
|
index 0000000..142ffec
|
|
--- /dev/null
|
|
+++ b/libres/dnscruft.c
|
|
@@ -0,0 +1,119 @@
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <sys/socket.h>
|
|
+#include <unistd.h>
|
|
+#include <fcntl.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <string.h>
|
|
+#include <ctype.h>
|
|
+#include <stdlib.h>
|
|
+#include <resolv.h>
|
|
+#include <net/if.h>
|
|
+#include <netdb.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+#ifdef __BIONIC__
|
|
+#include <sys/system_properties.h>
|
|
+#endif
|
|
+
|
|
+
|
|
+/* needs:
|
|
+ * _res
|
|
+ */
|
|
+
|
|
+int __dns_fd=-1;
|
|
+
|
|
+/* the ad-hoc internal API from hell ;-) */
|
|
+void __dns_make_fd(void);
|
|
+void __dns_make_fd6(void);
|
|
+void __dns_readstartfiles(void);
|
|
+int __dns_decodename(const unsigned char *packet,unsigned int offset,unsigned char *dest,
|
|
+ unsigned int maxlen,const unsigned char* behindpacket);
|
|
+
|
|
+void __dns_make_fd(void) {
|
|
+ int tmp;
|
|
+ struct sockaddr_in si;
|
|
+ if (__dns_fd>=0) return;
|
|
+ tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
|
+ if (tmp<0) return;
|
|
+ fcntl(tmp,F_SETFD,FD_CLOEXEC);
|
|
+ si.sin_family=AF_INET;
|
|
+ si.sin_port=0;
|
|
+ si.sin_addr.s_addr=INADDR_ANY;
|
|
+ if (bind(tmp,(struct sockaddr*)&si,sizeof(si))) return;
|
|
+ __dns_fd=tmp;
|
|
+}
|
|
+
|
|
+static int parsesockaddr(const char* c,void* x) {
|
|
+ struct sockaddr_in to;
|
|
+ if (inet_aton(c,&to.sin_addr)) {
|
|
+ to.sin_port=htons(53);
|
|
+ to.sin_family=AF_INET;
|
|
+ memmove(x,&to,sizeof(struct sockaddr_in));
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#define MAX_DNS_PROPERTIES 8
|
|
+#define DNS_PROP_NAME_PREFIX "net.dns"
|
|
+void __dns_readstartfiles(void) {
|
|
+#ifdef __BIONIC__
|
|
+ char propvalue[PROP_VALUE_MAX];
|
|
+ char propname[PROP_NAME_MAX];
|
|
+ int i;
|
|
+#endif
|
|
+
|
|
+ if (_diet_res.nscount>0)
|
|
+ return;
|
|
+
|
|
+ _diet_res.options=DIET_RES_RECURSE;
|
|
+
|
|
+#ifdef __BIONIC__
|
|
+ for(i = 1; i <= MAX_DNS_PROPERTIES; i++) {
|
|
+ snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, i);
|
|
+ if(__system_property_get(propname, propvalue) < 1) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (parsesockaddr(propvalue,&_diet_res.nsaddr_list[_diet_res.nscount]))
|
|
+ if (_diet_res.nscount<DIET_MAXNS)
|
|
+ ++_diet_res.nscount;
|
|
+ }
|
|
+#else
|
|
+ /* testing */
|
|
+ parsesockaddr("127.0.0.1",&_diet_res.nsaddr_list[_diet_res.nscount]);
|
|
+ ++_diet_res.nscount;
|
|
+#endif
|
|
+}
|
|
+
|
|
+/* return length of decoded data or -1 */
|
|
+int __dns_decodename(const unsigned char *packet,unsigned int offset,unsigned char *dest,
|
|
+ unsigned int maxlen,const unsigned char* behindpacket) {
|
|
+ const unsigned char *tmp;
|
|
+ const unsigned char *max=dest+maxlen;
|
|
+ const unsigned char *after=packet+offset;
|
|
+ int ok=0;
|
|
+ for (tmp=after; maxlen>0&&*tmp; ) {
|
|
+ if (tmp>=behindpacket) return -1;
|
|
+ if ((*tmp>>6)==3) { /* goofy DNS decompression */
|
|
+ unsigned int ofs=((unsigned int)(*tmp&0x3f)<<8)|*(tmp+1);
|
|
+ if (ofs>=(unsigned int)offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
|
|
+ if (after<tmp+2) after=tmp+2;
|
|
+ tmp=packet+ofs;
|
|
+ ok=0;
|
|
+ } else {
|
|
+ unsigned int duh;
|
|
+ if (dest+*tmp+1>max) return -1;
|
|
+ if (tmp+*tmp+1>=behindpacket) return -1;
|
|
+ for (duh=*tmp; duh>0; --duh)
|
|
+ *dest++=*++tmp;
|
|
+ *dest++='.'; ok=1;
|
|
+ ++tmp;
|
|
+ if (tmp>after) { after=tmp; if (!*tmp) ++after; }
|
|
+ }
|
|
+ }
|
|
+ if (ok) --dest;
|
|
+ *dest=0;
|
|
+ return after-packet;
|
|
+}
|
|
diff --git a/libres/dnscruft2.c b/libres/dnscruft2.c
|
|
new file mode 100644
|
|
index 0000000..db9782f
|
|
--- /dev/null
|
|
+++ b/libres/dnscruft2.c
|
|
@@ -0,0 +1,132 @@
|
|
+#include <string.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netdb.h>
|
|
+#include <stdlib.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+#include <arpa/nameser.h>
|
|
+#include <resolv.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+/* needs:
|
|
+ * __dns_decodename
|
|
+ * res_query
|
|
+ */
|
|
+
|
|
+extern int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
|
|
+ unsigned int maxlen,unsigned char* behindpacket);
|
|
+
|
|
+/* Oh boy, this interface sucks so badly, there are no words for it.
|
|
+ * Not one, not two, but _three_ error signalling methods! (*h_errnop
|
|
+ * nonzero? return value nonzero? *RESULT zero?) The glibc goons
|
|
+ * really outdid themselves with this one. */
|
|
+int __dns_gethostbyx_r(const char* name, struct hostent* result,
|
|
+ char *buf, size_t buflen,
|
|
+ struct hostent **RESULT, int *h_errnop, int lookfor) {
|
|
+ int names,ips;
|
|
+ char *cur;
|
|
+ char *max;
|
|
+ char inpkg[1500];
|
|
+ char* tmp;
|
|
+ int size;
|
|
+
|
|
+ if (lookfor==1) {
|
|
+ result->h_addrtype=AF_INET;
|
|
+ result->h_length=4;
|
|
+ } else {
|
|
+ result->h_addrtype=AF_INET6;
|
|
+ result->h_length=16;
|
|
+ }
|
|
+ result->h_aliases=(char**)(buf+8*sizeof(char*));
|
|
+ result->h_addr_list=(char**)buf;
|
|
+ result->h_aliases[0]=0;
|
|
+
|
|
+ cur=buf+16*sizeof(char*);
|
|
+ max=buf+buflen;
|
|
+ names=ips=0;
|
|
+
|
|
+ if ((size=diet_res_query(name,DIET_C_IN,lookfor,(unsigned char*)inpkg,512))<0) {
|
|
+invalidpacket:
|
|
+ *h_errnop=HOST_NOT_FOUND;
|
|
+ return -1;
|
|
+ }
|
|
+ {
|
|
+ tmp=inpkg+12;
|
|
+ {
|
|
+ unsigned char Name[257];
|
|
+ unsigned short q=((unsigned short)inpkg[4]<<8)+inpkg[5];
|
|
+ while (q>0) {
|
|
+ if (tmp>(char*)inpkg+size) goto invalidpacket;
|
|
+ while (*tmp) { tmp+=*tmp+1; if (tmp>(char*)inpkg+size) goto invalidpacket; }
|
|
+ tmp+=5;
|
|
+ --q;
|
|
+ }
|
|
+ if (tmp>inpkg+size) goto invalidpacket;
|
|
+ q=((unsigned short)inpkg[6]<<8)+inpkg[7];
|
|
+ if (q<1) goto nodata;
|
|
+ while (q>0) {
|
|
+ int decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
|
|
+ if (decofs<0) break;
|
|
+ tmp=inpkg+decofs;
|
|
+ --q;
|
|
+ if (tmp[0]!=0 || tmp[1]!=lookfor || /* TYPE != A */
|
|
+ tmp[2]!=0 || tmp[3]!=1) { /* CLASS != IN */
|
|
+ if (tmp[1]==5) { /* CNAME */
|
|
+ tmp+=10;
|
|
+ decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
|
|
+ if (decofs<0) break;
|
|
+ tmp=inpkg+decofs;
|
|
+ } else
|
|
+ break;
|
|
+ continue;
|
|
+ }
|
|
+ tmp+=10; /* skip type, class, TTL and length */
|
|
+ {
|
|
+ int slen;
|
|
+ if (lookfor==1 || lookfor==28) /* A or AAAA*/ {
|
|
+ slen=strlen((char*)Name);
|
|
+ if (cur+slen+8+(lookfor==28?12:0)>=max) { *h_errnop=NO_RECOVERY; return -1; }
|
|
+ } else {
|
|
+ if (lookfor==12) /* PTR */ {
|
|
+ decofs=__dns_decodename((unsigned char*)inpkg,(size_t)(tmp-(char*)inpkg),Name,256,(unsigned char*)inpkg+size);
|
|
+ if (decofs<0) break;
|
|
+ tmp=inpkg+decofs;
|
|
+ }
|
|
+ slen=strlen((char*)Name);
|
|
+ }
|
|
+ strcpy(cur,(char*)Name);
|
|
+ if (names==0)
|
|
+ result->h_name=cur;
|
|
+ else
|
|
+ result->h_aliases[names-1]=cur;
|
|
+ result->h_aliases[names]=0;
|
|
+ if (names<8) ++names;
|
|
+/* cur+=slen+1; */
|
|
+ cur+=(slen|3)+1;
|
|
+ result->h_addr_list[ips++] = cur;
|
|
+ if (lookfor==1) /* A */ {
|
|
+ memcpy(cur,tmp,4);
|
|
+ cur+=4; tmp+=4;
|
|
+ result->h_addr_list[ips]=0;
|
|
+ } else if (lookfor==28) /* AAAA */ {
|
|
+ memcpy(cur,tmp,16);
|
|
+ cur+=16; tmp+=16;
|
|
+ result->h_addr_list[ips]=0;
|
|
+ }
|
|
+ }
|
|
+/* puts(Name); */
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (!names) {
|
|
+nodata:
|
|
+ *h_errnop=NO_DATA;
|
|
+ return -1;
|
|
+ }
|
|
+ *h_errnop=0;
|
|
+ *RESULT=result;
|
|
+ return 0;
|
|
+}
|
|
diff --git a/libres/dnscruft3.c b/libres/dnscruft3.c
|
|
new file mode 100644
|
|
index 0000000..379dc8b
|
|
--- /dev/null
|
|
+++ b/libres/dnscruft3.c
|
|
@@ -0,0 +1,6 @@
|
|
+#include <netinet/in.h>
|
|
+#include <resolv.h>
|
|
+#include <netdb.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+struct diet_res_state _diet_res; /* don't ask. */
|
|
diff --git a/libres/freeaddrinfo.c b/libres/freeaddrinfo.c
|
|
new file mode 100644
|
|
index 0000000..f525d2c
|
|
--- /dev/null
|
|
+++ b/libres/freeaddrinfo.c
|
|
@@ -0,0 +1,14 @@
|
|
+#include <sys/socket.h>
|
|
+#include <stdlib.h>
|
|
+#include <netdb.h>
|
|
+#include <netinet/in.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+void diet_freeaddrinfo(struct addrinfo *res) {
|
|
+ while (res) {
|
|
+ struct addrinfo *duh;
|
|
+ duh=res;
|
|
+ res=res->ai_next;
|
|
+ free(duh);
|
|
+ }
|
|
+}
|
|
diff --git a/libres/gai_strerror.c b/libres/gai_strerror.c
|
|
new file mode 100644
|
|
index 0000000..311777e
|
|
--- /dev/null
|
|
+++ b/libres/gai_strerror.c
|
|
@@ -0,0 +1,14 @@
|
|
+#include <sys/socket.h>
|
|
+#include <netdb.h>
|
|
+
|
|
+const char* diet_gai_strerror(int error) {
|
|
+ switch (error) {
|
|
+ case EAI_FAMILY: return "family not supported";
|
|
+ case EAI_SOCKTYPE: return "socket type not supported";
|
|
+ case EAI_NONAME: return "unknown host";
|
|
+ case EAI_SERVICE: return "unknown service";
|
|
+ case EAI_MEMORY: return "memory allocation failure";
|
|
+ case EAI_AGAIN: return "temporary failure";
|
|
+ }
|
|
+ return "DNS error. Sorry.";
|
|
+}
|
|
diff --git a/libres/getaddrinfo.c b/libres/getaddrinfo.c
|
|
new file mode 100644
|
|
index 0000000..3c6f7ee
|
|
--- /dev/null
|
|
+++ b/libres/getaddrinfo.c
|
|
@@ -0,0 +1,137 @@
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <netdb.h>
|
|
+#include <net/if.h>
|
|
+#include <arpa/inet.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+/* XXX TODO FIXME */
|
|
+
|
|
+/* needs:
|
|
+ * gethostbyname2_r
|
|
+ */
|
|
+
|
|
+int diet_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res) {
|
|
+ struct addrinfo **tmp;
|
|
+ int family;
|
|
+ tmp=res; *res=0;
|
|
+ if (hints) {
|
|
+ if (hints->ai_family && hints->ai_family != PF_INET6 && hints->ai_family != PF_INET) return EAI_FAMILY;
|
|
+ if (hints->ai_socktype && hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM) return EAI_SOCKTYPE;
|
|
+ }
|
|
+ for (family=PF_INET6; ; family=PF_INET) {
|
|
+ if (!hints || hints->ai_family==family || hints->ai_family==AF_UNSPEC) { /* IPv6 addresses are OK */
|
|
+ struct hostent h;
|
|
+ struct hostent *H;
|
|
+ int herrno=0;
|
|
+ char buf[4096];
|
|
+ int lookupok=0, i;
|
|
+ char* interface;
|
|
+ h.h_addr_list=(char**)buf+16;
|
|
+ h.h_addr_list[1]=0;
|
|
+ if (node) {
|
|
+ if ((interface=strchr(node,'%'))) ++interface;
|
|
+ if (family==PF_INET6 && inet_pton(AF_INET,node,buf)) continue;
|
|
+ if (inet_pton(family,node,buf)>0) {
|
|
+ h.h_name=(char*)node;
|
|
+ h.h_addr_list[0]=buf;
|
|
+ lookupok=1;
|
|
+ } else if ((!hints || !(hints->ai_flags&AI_NUMERICHOST)) &&
|
|
+ !diet_gethostbyname2_r(node,family,&h,buf,4096,&H,&herrno)) {
|
|
+ lookupok=1;
|
|
+ } else {
|
|
+ if (herrno==TRY_AGAIN) { diet_freeaddrinfo(*res); return EAI_AGAIN; }
|
|
+ }
|
|
+ } else {
|
|
+ h.h_name=0;
|
|
+ h.h_addr_list[0]=buf;
|
|
+ interface=0;
|
|
+ memset(buf,0,16);
|
|
+ if (!hints || !(hints->ai_flags&AI_PASSIVE)) {
|
|
+ if (family==AF_INET) {
|
|
+ buf[0]=127; buf[3]=1;
|
|
+ } else
|
|
+ buf[15]=1;
|
|
+ }
|
|
+ lookupok=1;
|
|
+ }
|
|
+ if (lookupok) {
|
|
+
|
|
+ for (i=0; h.h_addr_list[i]; ++i) {
|
|
+ struct ai_v6 {
|
|
+ struct addrinfo ai;
|
|
+ union {
|
|
+ struct sockaddr_in6 ip6;
|
|
+ struct sockaddr_in ip4;
|
|
+ } ip;
|
|
+ char name[1];
|
|
+ } *foo;
|
|
+ unsigned short port;
|
|
+ int len;
|
|
+
|
|
+ len=sizeof(struct ai_v6)+(h.h_name?strlen(h.h_name):0);
|
|
+
|
|
+ if (!(foo=malloc(len))) goto error;
|
|
+ foo->ai.ai_next=0;
|
|
+ foo->ai.ai_addrlen=family==PF_INET6?sizeof(struct sockaddr_in6):sizeof(struct sockaddr_in);
|
|
+ foo->ai.ai_addr=(struct sockaddr*)&foo->ip;
|
|
+ if (family==PF_INET6) {
|
|
+ memset(&foo->ip,0,sizeof(foo->ip));
|
|
+ memmove(&foo->ip.ip6.sin6_addr,h.h_addr_list[i],16);
|
|
+ if (interface) foo->ip.ip6.sin6_scope_id=if_nametoindex(interface);
|
|
+ } else {
|
|
+ memmove(&foo->ip.ip4.sin_addr,h.h_addr_list[i],4);
|
|
+ }
|
|
+ foo->ip.ip6.sin6_family=foo->ai.ai_family=family;
|
|
+ if (h.h_name) {
|
|
+ foo->ai.ai_canonname=foo->name;
|
|
+ memmove(foo->name,h.h_name,strlen(h.h_name)+1);
|
|
+ } else
|
|
+ foo->ai.ai_canonname=0;
|
|
+
|
|
+ for (foo->ai.ai_socktype=SOCK_STREAM; ; foo->ai.ai_socktype=SOCK_DGRAM) {
|
|
+ char* type,* x;
|
|
+ if (foo->ai.ai_socktype==SOCK_STREAM) { /* TCP */
|
|
+ if (hints && hints->ai_socktype==SOCK_DGRAM) continue;
|
|
+ foo->ai.ai_protocol=IPPROTO_TCP;
|
|
+ type="tcp";
|
|
+ } else { /* UDP */
|
|
+ if (hints && hints->ai_socktype==SOCK_STREAM) break;
|
|
+ foo->ai.ai_protocol=IPPROTO_UDP;
|
|
+ type="udp";
|
|
+ }
|
|
+ port=htons(strtol(service?service:"0",&x,0));
|
|
+ if (*x) { /* service is not numeric :-( */
|
|
+ free(foo);
|
|
+ /* no getservbyname on android */
|
|
+ diet_freeaddrinfo(*res);
|
|
+ return EAI_SERVICE;
|
|
+ }
|
|
+ if (family==PF_INET6)
|
|
+ foo->ip.ip6.sin6_port=port;
|
|
+ else
|
|
+ foo->ip.ip4.sin_port=port;
|
|
+ if (!*tmp) *tmp=&(foo->ai); else (*tmp)->ai_next=&(foo->ai);
|
|
+ if (!(foo=malloc(len))) goto error;
|
|
+ memmove(foo,*tmp,len);
|
|
+ tmp=&(*tmp)->ai_next;
|
|
+ foo->ai.ai_addr=(struct sockaddr*)&foo->ip;
|
|
+ if (foo->ai.ai_canonname)
|
|
+ foo->ai.ai_canonname=foo->name;
|
|
+ if (foo->ai.ai_socktype==SOCK_DGRAM) break;
|
|
+ }
|
|
+ free(foo);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if (family==PF_INET) break;
|
|
+ }
|
|
+ if (*res==0) return EAI_NONAME; /* kludge kludge... */
|
|
+ return 0;
|
|
+error:
|
|
+ diet_freeaddrinfo(*res);
|
|
+ return EAI_MEMORY;
|
|
+}
|
|
diff --git a/libres/gethostbyname2_r.c b/libres/gethostbyname2_r.c
|
|
new file mode 100644
|
|
index 0000000..2558e5d
|
|
--- /dev/null
|
|
+++ b/libres/gethostbyname2_r.c
|
|
@@ -0,0 +1,35 @@
|
|
+#include <string.h>
|
|
+#include <strings.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netdb.h>
|
|
+#include <stdlib.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+/* needs:
|
|
+ * __dns_gethostbyx_r
|
|
+ */
|
|
+
|
|
+/* Oh boy, this interface sucks so badly, there are no words for it.
|
|
+ * Not one, not two, but _three_ error signalling methods! (*h_errnop
|
|
+ * nonzero? return value nonzero? *RESULT zero?) The glibc goons
|
|
+ * really outdid themselves with this one. */
|
|
+int diet_gethostbyname2_r(const char* name, int AF, struct hostent* result,
|
|
+ char *buf, size_t buflen,
|
|
+ struct hostent **RESULT, int *h_errnop) {
|
|
+ size_t L=strlen(name);
|
|
+ int lookfor=0;
|
|
+ switch (AF) {
|
|
+ case AF_INET: lookfor=1; break;
|
|
+ case AF_INET6: lookfor=28; break;
|
|
+ default: *h_errnop=EINVAL; return 1;
|
|
+ }
|
|
+ result->h_name=buf;
|
|
+ if (buflen<L) { *h_errnop=ERANGE; return 1; }
|
|
+ strcpy(buf,name);
|
|
+ return __dns_gethostbyx_r(name,result,buf+L,buflen-L,RESULT,h_errnop,lookfor);
|
|
+}
|
|
diff --git a/libres/h_errno.c b/libres/h_errno.c
|
|
new file mode 100644
|
|
index 0000000..fbdfd23
|
|
--- /dev/null
|
|
+++ b/libres/h_errno.c
|
|
@@ -0,0 +1 @@
|
|
+int diet_h_errno;
|
|
diff --git a/libres/res_init.c b/libres/res_init.c
|
|
new file mode 100644
|
|
index 0000000..c3a7e6d
|
|
--- /dev/null
|
|
+++ b/libres/res_init.c
|
|
@@ -0,0 +1,12 @@
|
|
+#include <resolv.h>
|
|
+#include <netdb.h>
|
|
+#include <netinet/in.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+extern void __dns_readstartfiles(void);
|
|
+
|
|
+int diet_res_init(void) {
|
|
+ _diet_res.nscount=0;
|
|
+ __dns_readstartfiles();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/libres/res_mkquery.c b/libres/res_mkquery.c
|
|
new file mode 100644
|
|
index 0000000..a8cece6
|
|
--- /dev/null
|
|
+++ b/libres/res_mkquery.c
|
|
@@ -0,0 +1,85 @@
|
|
+#include <resolv.h>
|
|
+#include <string.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netdb.h>
|
|
+#include <stdlib.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+#include <arpa/nameser.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+/* needs:
|
|
+ * _res
|
|
+ */
|
|
+
|
|
+static char dnspacket[]="\xfe\xfe\001\000\000\001\000\000\000\000\000\000";
|
|
+
|
|
+/*
|
|
+ 1 1 1 1 1 1
|
|
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ | ID |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ | QDCOUNT |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ | ANCOUNT |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ | NSCOUNT |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+ | ARCOUNT |
|
|
+ +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
+*/
|
|
+
|
|
+extern void __dns_make_fd(void);
|
|
+extern int __dns_fd;
|
|
+
|
|
+extern int __dns_servers;
|
|
+extern struct sockaddr __dns_server_ips[];
|
|
+
|
|
+extern void __dns_readstartfiles(void);
|
|
+
|
|
+int diet_res_mkquery(int op, const char *dname, int class, int type, char* data,
|
|
+ int datalen, const unsigned char* newrr, char* buf, int buflen) {
|
|
+ unsigned char packet[512];
|
|
+ unsigned long len;
|
|
+
|
|
+ memcpy(packet,dnspacket,12);
|
|
+ len=rand();
|
|
+ packet[0]=len;
|
|
+ packet[1]=len>>8;
|
|
+ len=0;
|
|
+ if ((_diet_res.options&DIET_RES_RECURSE)==0) packet[2]=0;
|
|
+ {
|
|
+ unsigned char* x;
|
|
+ const char* y,* tmp;
|
|
+ x=packet+12; y=dname;
|
|
+ while (*y) {
|
|
+ while (*y=='.') ++y;
|
|
+ for (tmp=y; *tmp && *tmp!='.'; ++tmp) ;
|
|
+ if (tmp-y > 63) return -1;
|
|
+ *x=tmp-y;
|
|
+ if (!(tmp-y)) break;
|
|
+ if ((len+=*x+1) > 254) return -1;
|
|
+ ++x;
|
|
+// if (x>=packet+510-(tmp-y)) { return -1; }
|
|
+ memmove(x,y,tmp-y);
|
|
+ x+=tmp-y;
|
|
+ if (!*tmp) {
|
|
+ *x=0;
|
|
+ break;
|
|
+ }
|
|
+ y=tmp;
|
|
+ }
|
|
+ *++x= 0; *++x= type; /* A */
|
|
+ *++x= 0; *++x= class; /* IN */
|
|
+ ++x;
|
|
+ if (x-packet>buflen) return -1;
|
|
+ memmove(buf,packet,x-packet);
|
|
+ return x-packet;
|
|
+ }
|
|
+}
|
|
diff --git a/libres/res_query.c b/libres/res_query.c
|
|
new file mode 100644
|
|
index 0000000..19898b7
|
|
--- /dev/null
|
|
+++ b/libres/res_query.c
|
|
@@ -0,0 +1,81 @@
|
|
+#include <resolv.h>
|
|
+#include <string.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/socket.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netdb.h>
|
|
+#include <stdlib.h>
|
|
+#include <arpa/inet.h>
|
|
+#include <poll.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+#include <arpa/nameser.h>
|
|
+#include <fcntl.h>
|
|
+#include <sys/time.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+/* needs:
|
|
+ * __dns_fd
|
|
+ * __dns_make_fd
|
|
+ * __dns_readstartfiles
|
|
+ * h_errno
|
|
+ * diet_res_mkquery
|
|
+ * _res
|
|
+ */
|
|
+
|
|
+extern void __dns_make_fd(void);
|
|
+extern int __dns_fd;
|
|
+
|
|
+extern void __dns_readstartfiles(void);
|
|
+
|
|
+int diet_res_query(const char *dname, int class, int type, unsigned char *answer, int anslen) {
|
|
+ unsigned char packet[512];
|
|
+ int size;
|
|
+ struct pollfd duh[2];
|
|
+ __dns_make_fd();
|
|
+
|
|
+ __dns_readstartfiles();
|
|
+ if ((size=diet_res_mkquery(DIET_QUERY,dname,class,type,0,0,0,(char*)packet,512))<0) { diet_h_errno=NO_RECOVERY; return -1; }
|
|
+ {
|
|
+ {
|
|
+ int i; /* current server */
|
|
+ int j; /* timeout count down */
|
|
+ struct timeval last,now;
|
|
+
|
|
+ i=0;
|
|
+ duh[0].events=POLLIN;
|
|
+ duh[0].fd=0;
|
|
+ last.tv_sec=0;
|
|
+ for (j=20; j>0; --j) {
|
|
+ gettimeofday(&now,0);
|
|
+ if (now.tv_sec-last.tv_sec>10) {
|
|
+ duh[0].fd=__dns_fd;
|
|
+ sendto(__dns_fd,packet,size,0,(struct sockaddr*)&(_diet_res.nsaddr_list[i]),sizeof(struct sockaddr));
|
|
+ last=now;
|
|
+ }
|
|
+ if (++i >= _diet_res.nscount) i=0;
|
|
+ if (poll(duh,1,1000) == 1) {
|
|
+ /* read and parse answer */
|
|
+ unsigned char inpkg[1500];
|
|
+ int len=read(duh[0].fd,inpkg,sizeof(inpkg));
|
|
+ /* header, question, answer, authority, additional */
|
|
+ if (inpkg[0]!=packet[0] || inpkg[1]!=packet[1]) continue; /* wrong ID */
|
|
+ if ((inpkg[2]&0xf9) != (_diet_res.options&DIET_RES_RECURSE?0x81:0x80)) continue; /* not answer */
|
|
+ if ((inpkg[3]&0x0f) != 0) {
|
|
+ diet_h_errno=HOST_NOT_FOUND;
|
|
+ return -1;
|
|
+ } /* error */
|
|
+ if (len>anslen) {
|
|
+ diet_h_errno=NO_RECOVERY;
|
|
+ return -1;
|
|
+ }
|
|
+ memcpy(answer,inpkg,len);
|
|
+ return len;
|
|
+ }
|
|
+/*kaputt:*/
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ diet_h_errno=TRY_AGAIN;
|
|
+ return -1;
|
|
+}
|
|
diff --git a/libres/test.c b/libres/test.c
|
|
new file mode 100644
|
|
index 0000000..45095d8
|
|
--- /dev/null
|
|
+++ b/libres/test.c
|
|
@@ -0,0 +1,105 @@
|
|
+#include <stdio.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdarg.h>
|
|
+#include <unistd.h>
|
|
+#include <fcntl.h>
|
|
+#include <sys/socket.h>
|
|
+#include <sys/poll.h>
|
|
+#include <netinet/icmp6.h>
|
|
+#include <netinet/ip_icmp.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netinet/ip6.h>
|
|
+#include <netdb.h>
|
|
+#include <arpa/inet.h>
|
|
+#include "dietdns.h"
|
|
+
|
|
+union common_sockaddr {
|
|
+ struct sockaddr sa;
|
|
+ struct sockaddr_in sin;
|
|
+ struct sockaddr_in6 sin6;
|
|
+};
|
|
+typedef union common_sockaddr sockaddr_any;
|
|
+
|
|
+static int getaddr (const char *name, sockaddr_any *addr, int af) {
|
|
+ int ret;
|
|
+ struct addrinfo hints, *ai, *res = NULL;
|
|
+
|
|
+ memset (&hints, 0, sizeof (hints));
|
|
+ hints.ai_family = af;
|
|
+ hints.ai_socktype = SOCK_DGRAM;
|
|
+ hints.ai_flags = AI_ADDRCONFIG;
|
|
+
|
|
+ ret = diet_getaddrinfo (name, NULL, &hints, &res);
|
|
+ if (ret) {
|
|
+ fprintf (stderr, "%s: %s\n", name, diet_gai_strerror (ret));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (ai = res; ai; ai = ai->ai_next) {
|
|
+ if (ai->ai_family == af) break;
|
|
+ }
|
|
+ if (!ai) ai = res; /* anything... */
|
|
+
|
|
+ if (ai->ai_addrlen > sizeof (*addr))
|
|
+ return -1; /* paranoia */
|
|
+ memcpy (addr, ai->ai_addr, ai->ai_addrlen);
|
|
+
|
|
+ if(res != NULL)
|
|
+ diet_freeaddrinfo (res);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void printaddr(sockaddr_any *addr) {
|
|
+ char addr_str[INET6_ADDRSTRLEN];
|
|
+
|
|
+ if(addr->sa.sa_family == AF_INET) {
|
|
+ printf("family = AF_INET\n");
|
|
+ if(inet_ntop(addr->sin.sin_family, &addr->sin.sin_addr, (char *)&addr_str, sizeof(addr_str)) == NULL) {
|
|
+ perror("inet_ntop failed");
|
|
+ return;
|
|
+ }
|
|
+ printf("addr = %s\n", addr_str);
|
|
+ } else if(addr->sa.sa_family == AF_INET6) {
|
|
+ printf("family = AF_INET6\n");
|
|
+ if(inet_ntop(addr->sin6.sin6_family, &addr->sin6.sin6_addr, (char *)&addr_str, sizeof(addr_str)) == NULL) {
|
|
+ perror("inet_ntop failed");
|
|
+ return;
|
|
+ }
|
|
+ printf("addr = %s\n", addr_str);
|
|
+ } else {
|
|
+ printf("unknown family = %d\n",addr->sa.sa_family);
|
|
+ }
|
|
+}
|
|
+
|
|
+int main() {
|
|
+ sockaddr_any dst_addr = {{ 0, }, };
|
|
+ struct sockaddr_in lsa_u;
|
|
+
|
|
+ if (getaddr("www.datapipe.net", &dst_addr, AF_INET) < 0) {
|
|
+ fprintf(stderr, "getaddr failed\n");
|
|
+ } else {
|
|
+ printaddr(&dst_addr);
|
|
+ }
|
|
+
|
|
+ if (getaddr("www.datapipe.net", &dst_addr, AF_INET6) < 0) {
|
|
+ fprintf(stderr, "getaddr failed\n");
|
|
+ } else {
|
|
+ printaddr(&dst_addr);
|
|
+ }
|
|
+
|
|
+ inet_aton("127.0.0.1",&lsa_u.sin_addr);
|
|
+ lsa_u.sin_port=htons(53);
|
|
+ lsa_u.sin_family=AF_INET;
|
|
+
|
|
+ _diet_res.nscount = 1;
|
|
+ _diet_res.nsaddr_list[0] = lsa_u;
|
|
+
|
|
+ if (getaddr("www.datapipe.net", &dst_addr, AF_INET6) < 0) {
|
|
+ fprintf(stderr, "getaddr failed\n");
|
|
+ } else {
|
|
+ printaddr(&dst_addr);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/networking/nslookup.c b/networking/nslookup.c
|
|
index f4fd407..465f4b4 100644
|
|
--- a/networking/nslookup.c
|
|
+++ b/networking/nslookup.c
|
|
@@ -26,6 +26,9 @@
|
|
//usage: "Address: 127.0.0.1\n"
|
|
|
|
#include <resolv.h>
|
|
+#include <netinet/in.h>
|
|
+#include <netdb.h>
|
|
+#include "../libres/dietdns.h"
|
|
#include "libbb.h"
|
|
|
|
/*
|
|
@@ -78,7 +81,7 @@ static int print_host(const char *hostname, const char *header)
|
|
* for each possible socket type (tcp,udp,raw...): */
|
|
hint.ai_socktype = SOCK_STREAM;
|
|
// hint.ai_flags = AI_CANONNAME;
|
|
- rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
|
|
+ rc = diet_getaddrinfo(hostname, NULL /*service*/, &hint, &result);
|
|
|
|
if (rc == 0) {
|
|
struct addrinfo *cur = result;
|
|
@@ -109,7 +112,7 @@ static int print_host(const char *hostname, const char *header)
|
|
#endif
|
|
}
|
|
if (ENABLE_FEATURE_CLEAN_UP && result)
|
|
- freeaddrinfo(result);
|
|
+ diet_freeaddrinfo(result);
|
|
return (rc != 0);
|
|
}
|
|
|
|
@@ -119,11 +122,11 @@ static void server_print(void)
|
|
char *server;
|
|
struct sockaddr *sa;
|
|
|
|
-#if ENABLE_FEATURE_IPV6
|
|
- sa = (struct sockaddr*)_res._u._ext.nsaddrs[0];
|
|
+#if 0
|
|
+ sa = (struct sockaddr*)_diet_res._u._ext.nsaddrs[0];
|
|
if (!sa)
|
|
#endif
|
|
- sa = (struct sockaddr*)&_res.nsaddr_list[0];
|
|
+ sa = (struct sockaddr*)&_diet_res.nsaddr_list[0];
|
|
server = xmalloc_sockaddr2dotted_noport(sa);
|
|
|
|
print_host(server, "Server:");
|
|
@@ -142,11 +145,11 @@ static void set_default_dns(const char *server)
|
|
lsa = xhost2sockaddr(server, 53);
|
|
|
|
if (lsa->u.sa.sa_family == AF_INET) {
|
|
- _res.nscount = 1;
|
|
+ _diet_res.nscount = 1;
|
|
/* struct copy */
|
|
- _res.nsaddr_list[0] = lsa->u.sin;
|
|
+ _diet_res.nsaddr_list[0] = lsa->u.sin;
|
|
}
|
|
-#if ENABLE_FEATURE_IPV6
|
|
+#if 0
|
|
/* Hoped libc can cope with IPv4 address there too.
|
|
* No such luck, glibc 2.4 segfaults even with IPv6,
|
|
* maybe I misunderstand how to make glibc use IPv6 addr?
|
|
@@ -155,9 +158,9 @@ static void set_default_dns(const char *server)
|
|
// glibc neither SEGVs nor sends any dgrams with this
|
|
// (strace shows no socket ops):
|
|
//_res.nscount = 0;
|
|
- _res._u._ext.nscount = 1;
|
|
+ _diet_res._u._ext.nscount = 1;
|
|
/* store a pointer to part of malloc'ed lsa */
|
|
- _res._u._ext.nsaddrs[0] = &lsa->u.sin6;
|
|
+ _diet_res._u._ext.nsaddrs[0] = &lsa->u.sin6;
|
|
/* must not free(lsa)! */
|
|
}
|
|
#endif
|
|
@@ -176,7 +179,7 @@ int nslookup_main(int argc, char **argv)
|
|
|
|
/* initialize DNS structure _res used in printing the default
|
|
* name server and in the explicit name server option feature. */
|
|
- res_init();
|
|
+ diet_res_init();
|
|
/* rfc2133 says this enables IPv6 lookups */
|
|
/* (but it also says "may be enabled in /etc/resolv.conf") */
|
|
/*_res.options |= RES_USE_INET6;*/
|
|
--
|
|
1.7.10.4
|
|
|