summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/dietlibc/libcruft/dnscruft.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/dietlibc/libcruft/dnscruft.c')
-rw-r--r--mdk-stage1/dietlibc/libcruft/dnscruft.c132
1 files changed, 99 insertions, 33 deletions
diff --git a/mdk-stage1/dietlibc/libcruft/dnscruft.c b/mdk-stage1/dietlibc/libcruft/dnscruft.c
index d7a0efa50..bd8bee79a 100644
--- a/mdk-stage1/dietlibc/libcruft/dnscruft.c
+++ b/mdk-stage1/dietlibc/libcruft/dnscruft.c
@@ -7,51 +7,100 @@
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
+#include <resolv.h>
+#include <net/if.h>
+#include "dietfeatures.h"
int __dns_fd=-1;
+#ifdef WANT_IPV6_DNS
+int __dns_fd6=-1;
+#endif
-void __dns_make_fd() {
+/* the ad-hoc internal API from hell ;-) */
+void __dns_make_fd(void);
+void __dns_make_fd6(void);
+void __dns_readstartfiles(void);
+int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
+ unsigned int maxlen,unsigned char* behindpacket);
+
+void __dns_make_fd(void) {
int tmp;
struct sockaddr_in si;
- if (__dns_fd>0) return;
+ if (__dns_fd>=0) return;
tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
- if (tmp<0) {
- perror("__dns_make_fd!socket");
- return;
- }
+ if (tmp<0) return;
si.sin_family=AF_INET;
si.sin_port=0;
si.sin_addr.s_addr=INADDR_ANY;
- if (bind(tmp,(struct sockaddr*)&si,sizeof(si))) {
- perror("__dns_make_fd!bind");
- return;
- }
+ if (bind(tmp,(struct sockaddr*)&si,sizeof(si))) return;
__dns_fd=tmp;
}
-int __dns_servers=0;
-struct sockaddr __dns_server_ips[8];
+#ifdef WANT_IPV6_DNS
+void __dns_make_fd6(void) {
+ int tmp;
+ struct sockaddr_in6 si;
+ if (__dns_fd6>=0) return;
+ tmp=socket(PF_INET6,SOCK_DGRAM,IPPROTO_UDP);
+ if (tmp<0) return;
+ si.sin6_family=AF_INET6;
+ si.sin6_port=0;
+ memset(&si.sin6_addr,0,16);
+ if (bind(tmp,(struct sockaddr*)&si,sizeof(si))) return;
+ __dns_fd6=tmp;
+}
+#endif
-int __dns_search=0;
+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_pad));
+ return 1;
+#ifdef WANT_IPV6_DNS
+ } else {
+ struct sockaddr_in6 to6;
+ char* d=strchr(c,'%');
+ to6.sin6_flowinfo=to6.sin6_scope_id=0;
+ if (d)
+ to6.sin6_scope_id=if_nametoindex(d+1);
+ if (inet_pton(AF_INET6,c,&to6.sin6_addr)) {
+ to6.sin6_port=htons(53);
+ to6.sin6_family=AF_INET6;
+ memmove(x,&to6,sizeof(struct sockaddr_in_pad));
+ return 1;
+ }
+#endif
+ }
+ return 0;
+}
+
+#ifdef WANT_FULL_RESOLV_CONF
+int __dns_search;
char *__dns_domains[8];
+#endif
-void __dns_readstartfiles() {
+void __dns_readstartfiles(void) {
int fd;
- char *buf=alloca(4096);
+ char __buf[4096];
+ char *buf=__buf;
int len;
- if (__dns_servers>0) return;
+ if (_res.nscount>0) return;
{
struct sockaddr_in to;
+#ifdef WANT_IPV6_DNS
+ struct sockaddr_in6 to6;
+#endif
char *cacheip=getenv("DNSCACHEIP");
- if (cacheip) {
- to.sin_port=htons(53);
- to.sin_family=AF_INET;
- if (inet_aton(cacheip,&to.sin_addr)) {
- memmove(__dns_server_ips,&to,sizeof(struct sockaddr));
- ++__dns_servers;
- }
- }
+#ifdef WANT_FULL_RESOLV_CONF
+ __dns_search=0;
+#endif
+ if (cacheip)
+ if (parsesockaddr(cacheip,_res.nsaddr_list))
+ ++_res.nscount;
}
+ _res.options=RES_RECURSE;
if ((fd=open("/etc/resolv.conf",O_RDONLY))<0) return;
len=read(fd,buf,4096);
close(fd);
@@ -65,21 +114,35 @@ void __dns_readstartfiles() {
{
char *tmp=buf;
struct sockaddr_in i;
+ char save;
while (buf<last && !isspace(*buf)) ++buf;
if (buf>=last) break;
+ save=*buf;
*buf=0;
- if (inet_aton(tmp,&i.sin_addr)) {
- i.sin_family=AF_INET;
- i.sin_port=htons(53);
- memmove(&__dns_server_ips[__dns_servers],&i,sizeof(struct sockaddr));
- if (__dns_servers<8) ++__dns_servers;
- }
+ if (parsesockaddr(tmp,&_res.nsaddr_list[_res.nscount]))
+ if (_res.nscount<MAXNS) ++_res.nscount;
+ *buf=save;
}
}
}
- if (!strncmp(buf,"search",6) || !strncmp(buf,"domain",6)) {
+#ifdef WANT_FULL_RESOLV_CONF
+ else if (!strncmp(buf,"search",6) || !strncmp(buf,"domain",6)) {
buf+=6;
+ while (buf<last && *buf!='\n') {
+ char save;
+ while (buf<last && (*buf==',' || isblank(*buf))) ++buf;
+ __dns_domains[__dns_search]=buf;
+ while (buf<last && (*buf=='.' || *buf=='-' || isalnum(*buf))) ++buf;
+ save=*buf;
+ if (buf<last) *buf=0;
+ if (__dns_domains[__dns_search]<buf &&
+ (__dns_domains[__dns_search]=strdup(__dns_domains[__dns_search])))
+ ++__dns_search;
+ if (buf<last) *buf=save;
+ }
+ continue;
}
+#endif
while (buf<last && *buf!='\n') ++buf;
while (buf<last && *buf=='\n') ++buf;
}
@@ -87,21 +150,24 @@ void __dns_readstartfiles() {
}
/* return length of decoded data or -1 */
-int __dns_decodename(unsigned char *packet,int offset,unsigned char *dest,int maxlen) {
+int __dns_decodename(unsigned char *packet,unsigned int offset,unsigned char *dest,
+ unsigned int maxlen,unsigned char* behindpacket) {
unsigned char *tmp;
unsigned char *max=dest+maxlen;
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>=offset) return -1; /* RFC1035: "pointer to a _prior_ occurrance" */
+ 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;