--- ../busybox-1.23.2.orig/Makefile 2015-03-23 06:07:18.000000000 +0300 +++ ./Makefile 2015-09-25 18:02:33.569380577 +0300 @@ -476,6 +476,7 @@ init/ \ libbb/ \ libpwdgrp/ \ + libres/ \ loginutils/ \ mailutils/ \ miscutils/ \ --- ../busybox-1.23.2.orig/libres/dietdns.h 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/dietdns.h 2015-09-25 18:03:21.450002344 +0300 @@ -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 --- ../busybox-1.23.2.orig/libres/dn_expand.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/dn_expand.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,12 @@ +#include +#include +#include +#include +#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); +} --- ../busybox-1.23.2.orig/libres/dnscruft2.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/dnscruft2.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,132 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} --- ../busybox-1.23.2.orig/libres/dnscruft3.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/dnscruft3.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,6 @@ +#include +#include +#include +#include "dietdns.h" + +struct diet_res_state _diet_res; /* don't ask. */ --- ../busybox-1.23.2.orig/libres/dnscruft.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/dnscruft.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dietdns.h" + +#ifdef __BIONIC__ +#include +#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; +} + +int getprop(const char *propname, char *propvalue) { + int rv = 0; + int fd[2]; + int status; + int pid; + FILE *fp; + const char *argv[3] = {"getprop", propname}; + pipe(fd); + pid = fork(); + if (pid == 0) { + close(fd[0]); + dup2(fd[1], STDOUT_FILENO); + close(fd[1]); + execvp(argv[0], argv); + exit(-1); + } else if (pid != -1) { + close(fd[1]); + wait(&status); + if (status == 0) { + fp = fdopen(fd[0], "r"); + if (fp != NULL) { + if (fgets(propvalue, PROP_VALUE_MAX, fp) != NULL) { + rv = 1; + } + fclose(fp); + } + } + } + return rv; +} + +#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 (getprop(propname, propvalue) > 0) { + if (parsesockaddr(propvalue,&_diet_res.nsaddr_list[_diet_res.nscount])) + if (_diet_res.nscount0&&*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 (aftermax) 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; +} --- ../busybox-1.23.2.orig/libres/freeaddrinfo.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/freeaddrinfo.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,14 @@ +#include +#include +#include +#include +#include "dietdns.h" + +void diet_freeaddrinfo(struct addrinfo *res) { + while (res) { + struct addrinfo *duh; + duh=res; + res=res->ai_next; + free(duh); + } +} --- ../busybox-1.23.2.orig/libres/gai_strerror.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/gai_strerror.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,14 @@ +#include +#include + +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."; +} --- ../busybox-1.23.2.orig/libres/getaddrinfo.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/getaddrinfo.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} --- ../busybox-1.23.2.orig/libres/gethostbyname2_r.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/gethostbyname2_r.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 +# +# 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 --- ../busybox-1.23.2.orig/libres/Makefile 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/Makefile 2015-09-25 18:03:21.450002344 +0300 @@ -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 $< --- ../busybox-1.23.2.orig/libres/README 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/README 2015-09-25 18:03:21.450002344 +0300 @@ -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/ --- ../busybox-1.23.2.orig/libres/res_init.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/res_init.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,12 @@ +#include +#include +#include +#include "dietdns.h" + +extern void __dns_readstartfiles(void); + +int diet_res_init(void) { + _diet_res.nscount=0; + __dns_readstartfiles(); + return 0; +} --- ../busybox-1.23.2.orig/libres/res_mkquery.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/res_mkquery.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + } +} --- ../busybox-1.23.2.orig/libres/res_query.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/res_query.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} --- ../busybox-1.23.2.orig/libres/test.c 1970-01-01 03:00:00.000000000 +0300 +++ ./libres/test.c 2015-09-25 18:03:21.450002344 +0300 @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} --- ../busybox-1.29.2.orig/networking/nslookup.c 2018-07-02 14:23:06.000000000 +0300 +++ ./networking/nslookup.c 2018-08-13 11:29:38.331647824 +0300 @@ -36,8 +36,10 @@ #include #include /* for IFNAMSIZ */ +#include //#include -//#include +#include +#include "../libres/dietdns.h" #include "libbb.h" #include "common_bufsiz.h" @@ -106,7 +108,7 @@ * 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; @@ -137,7 +139,7 @@ #endif } if (ENABLE_FEATURE_CLEAN_UP && result) - freeaddrinfo(result); + diet_freeaddrinfo(result); return (rc != 0); } @@ -147,11 +149,11 @@ 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:"); @@ -173,11 +175,11 @@ 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? @@ -186,9 +188,9 @@ // 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 @@ -207,7 +209,7 @@ /* 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;*/ --- ../busybox-1.23.2.orig/libbb/xconnect.c 2015-09-03 05:15:55.000000000 +0300 +++ ./libbb/xconnect.c 2016-01-09 22:43:14.346436304 +0300 @@ -12,6 +12,7 @@ #include #include #include +#include "../libres/dietdns.h" #include "libbb.h" int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval) @@ -282,7 +283,7 @@ * for each possible socket type (tcp,udp,raw...): */ hint.ai_socktype = SOCK_STREAM; hint.ai_flags = ai_flags & ~DIE_ON_ERROR; - rc = getaddrinfo(host, NULL, &hint, &result); + rc = diet_getaddrinfo(host, NULL, &hint, &result); if (rc || !result) { bb_error_msg("bad address '%s'", org_host); if (ai_flags & DIE_ON_ERROR) @@ -309,7 +310,7 @@ set_nport(&r->u.sa, htons(port)); ret: if (result) - freeaddrinfo(result); + diet_freeaddrinfo(result); return r; } #if !ENABLE_FEATURE_IPV6