2 * Copyright (c) 2006 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <arpa/nameser.h>
23 #include <arpa/nameser8_compat.h>
43 #define MIN(a,b) ((a)<(b)?(a):(b))
47 static int dns_write(int, int, char *, int, char);
48 static void dns_query(int, int, char *, int);
50 struct sockaddr_in peer;
54 char activepacket[4096];
64 open_dns(const char *domain, int localport, in_addr_t listen_ip)
68 struct sockaddr_in addr;
70 memset(&addr, 0, sizeof(addr));
71 addr.sin_family = AF_INET;
72 addr.sin_port = htons(localport);
73 /* listen_ip already in network byte order from inet_addr, or 0 */
74 addr.sin_addr.s_addr = listen_ip;
76 fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
84 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag));
86 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
88 if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
93 // Save top domain used
94 strncpy(topdomain, domain, sizeof(topdomain) - 1);
95 topdomain[sizeof(topdomain) - 1] = '\0';
97 printf("Opened UDP socket\n");
103 dns_settarget(const char *host)
107 // Init dns target struct
108 h = gethostbyname(host);
110 printf("Could not resolve name %s, exiting\n", host);
114 memset(&peer, 0, sizeof(peer));
115 peer.sin_family = AF_INET;
116 peer.sin_port = htons(53);
117 peer.sin_addr = *((struct in_addr *) h->h_addr);
135 return (packetlen != 0);
139 dns_send_chunk(int fd)
146 avail = packetlen - packetpos;
147 lastlen = dns_write(fd, ++chunkid, p, avail, 0);
151 dns_handle_tun(int fd, char *data, int len)
153 memcpy(activepacket, data, MIN(len, sizeof(activepacket)));
170 data[0] = (pingid & 0xFF00) >> 8;
171 data[1] = (pingid & 0xFF);
172 dns_write(dns_fd, ++pingid, data, 2, 'P');
176 dns_handshake(int dns_fd)
179 data[0] = (pingid & 0xFF00) >> 8;
180 data[1] = (pingid & 0xFF);
181 dns_write(dns_fd, ++pingid, data, 2, 'H');
185 dns_query(int fd, int id, char *host, int type)
194 memset(buf, 0, sizeof(buf));
196 header = (HEADER*)buf;
198 header->id = htons(id);
206 header->qdcount = htons(1);
207 header->arcount = htons(1);
209 p = buf + sizeof(HEADER);
210 p += dns_encode_hostname(host, p, strlen(host));
216 putbyte(&p, 0x00); //Root
217 putshort(&p, 0x0029); // OPT
218 putshort(&p, 0x1000); // Payload size: 4096
219 putshort(&p, 0x0000); // Higher bits/edns version
220 putshort(&p, 0x8000); // Z
221 putshort(&p, 0x0000); // Data length
223 peerlen = sizeof(peer);
226 sendto(fd, buf, len, 0, (struct sockaddr*)&peer, peerlen);
230 dns_write(int fd, int id, char *buf, int len, char flag)
238 avail = 0xFF - strlen(topdomain) - 2;
239 memset(data, 0, sizeof(data));
241 written = encode_data(buf, len, avail, d, flag);
242 encoded = strlen(data);
247 strncpy(d, topdomain, strlen(topdomain)+1);
249 dns_query(fd, id, data, T_NULL);
254 dns_read(int fd, char *buf, int buflen)
258 char packet[64*1024];
259 struct sockaddr_in from;
262 addrlen = sizeof(struct sockaddr);
263 r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
269 header = (HEADER*)packet;
270 if (dns_sending() && chunkid == ntohs(header->id)) {
271 /* Got ACK on sent packet */
272 packetpos += lastlen;
273 if (packetpos == packetlen) {
274 /* Packet completed */
283 return dns_parse_reply(buf, buflen, packet, r);
287 dns_parse_reply(char *outbuf, int buflen, char *packet, int packetlen)
302 header = (HEADER*)packet;
304 data = packet + sizeof(HEADER);
306 if(header->qr) { /* qr=1 => response */
307 qdcount = ntohs(header->qdcount);
308 ancount = ntohs(header->ancount);
313 readname(packet, packetlen, &data, name, sizeof(name));
314 readshort(packet, &data, &type);
315 readshort(packet, &data, &class);
318 readname(packet, packetlen, &data, name, sizeof(name));
319 readshort(packet, &data, &type);
320 readshort(packet, &data, &class);
321 readlong(packet, &data, &ttl);
322 readshort(packet, &data, &rlen);
323 rv = MIN(rlen, sizeof(rdata));
324 readdata(packet, &data, rdata, rv);
327 if(type == T_NULL && rv > 2) {
328 rv = MIN(rv, buflen);
329 memcpy(outbuf, rdata, rv);
337 dns_encode_hostname(const char *host, char *buffer, int size)
345 memset(buffer, 0, size);
349 word = strtok(h, ".");
351 if (strlen(word) > 63 || strlen(word) > left) {
354 left -= (strlen(word) + 1);
355 *p++ = (char)strlen(word);
356 memcpy(p, word, strlen(word));
359 word = strtok(NULL, ".");
370 dnsd_send(int fd, struct query *q, char *data, int datalen)
378 memset(buf, 0, sizeof(buf));
381 header = (HEADER*)buf;
383 header->id = htons(q->id);
391 header->qdcount = htons(1);
392 header->ancount = htons(1);
394 p = buf + sizeof(HEADER);
396 name = 0xc000 | ((p - buf) & 0x3fff);
397 p += dns_encode_hostname(q->name, p, strlen(q->name));
398 putshort(&p, q->type);
402 putshort(&p, q->type);
408 putshort(&p, datalen);
409 putdata(&p, data, datalen);
412 sendto(fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen);
416 decodepacket(const char *name, char *buf, int buflen)
421 domain = strstr(name, topdomain);
423 len = decode_data(buf, buflen, name, domain);
430 dnsd_read(int fd, struct query *q, char *buf, int buflen)
442 char packet[64*1024];
443 struct sockaddr_in from;
445 addrlen = sizeof(struct sockaddr);
446 r = recvfrom(fd, packet, sizeof(packet), 0, (struct sockaddr*)&from, &addrlen);
448 if (r >= sizeof(HEADER)) {
449 header = (HEADER*)packet;
451 id = ntohs(header->id);
453 data = packet + sizeof(HEADER);
456 qdcount = ntohs(header->qdcount);
459 readname(packet, r, &data, name, sizeof(name) -1);
461 readshort(packet, &data, &type);
462 readshort(packet, &data, &class);
464 strncpy(q->name, name, 257);
467 q->fromlen = addrlen;
468 memcpy((struct sockaddr*)&q->from, (struct sockaddr*)&from, addrlen);
470 rv = decodepacket(name, buf, buflen);
473 } else if (r < 0) { // Error
476 } else { // Packet too small to be dns protocol