1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
#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>
int __dns_fd=-1;
void __dns_make_fd() {
int tmp;
struct sockaddr_in si;
if (__dns_fd>0) return;
tmp=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
if (tmp<0) {
perror("__dns_make_fd!socket");
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;
}
__dns_fd=tmp;
}
int __dns_servers=0;
struct sockaddr __dns_server_ips[8];
int __dns_search=0;
char *__dns_domains[8];
void __dns_readstartfiles() {
int fd;
char *buf=alloca(4096);
int len;
if (__dns_servers>0) return;
{
struct sockaddr_in to;
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;
}
}
}
if ((fd=open("/etc/resolv.conf",O_RDONLY))<0) return;
len=read(fd,buf,4096);
close(fd);
{
char *last=buf+len;
for (; buf<last;) {
if (!strncmp(buf,"nameserver",10)) {
buf+=10;
while (buf<last && *buf!='\n') {
while (buf<last && isblank(*buf)) ++buf;
{
char *tmp=buf;
struct sockaddr_in i;
while (buf<last && !isspace(*buf)) ++buf;
if (buf>=last) break;
*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 (!strncmp(buf,"search",6) || !strncmp(buf,"domain",6)) {
buf+=6;
}
while (buf<last && *buf!='\n') ++buf;
while (buf<last && *buf=='\n') ++buf;
}
}
}
/* return length of decoded data or -1 */
int __dns_decodename(unsigned char *packet,int offset,unsigned char *dest,int maxlen) {
unsigned char *tmp;
unsigned char *max=dest+maxlen;
unsigned char *after=packet+offset;
int ok=0;
for (tmp=after; maxlen>0&&*tmp; ) {
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 (after<tmp+2) after=tmp+2;
tmp=packet+ofs;
ok=0;
} else {
unsigned int duh;
if (dest+*tmp+1>max) 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;
}
|