Fix issue #33, respond to NS requests
This commit is contained in:
parent
f4cd876ace
commit
9d3f87ddcc
|
@ -19,6 +19,8 @@ CHANGES:
|
||||||
- Added capability to forward DNS queries outside tunnel domain to
|
- Added capability to forward DNS queries outside tunnel domain to
|
||||||
a nameserver on localhost. Use -b port to enable.
|
a nameserver on localhost. Use -b port to enable.
|
||||||
- iodine client now shuts down if it detects a server restart.
|
- iodine client now shuts down if it detects a server restart.
|
||||||
|
- iodined now replies to NS request on its own domain, fixes issue #33.
|
||||||
|
The destination IP address is sent as reply.
|
||||||
|
|
||||||
2008-08-06: 0.4.2 "Opened Zone"
|
2008-08-06: 0.4.2 "Opened Zone"
|
||||||
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
|
- Applied a few small patches from Maxim Bourmistrov and Gregor Herrmann
|
||||||
|
|
79
src/dns.c
79
src/dns.c
|
@ -98,6 +98,85 @@ dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain)
|
||||||
|
{
|
||||||
|
HEADER *header;
|
||||||
|
int len;
|
||||||
|
short name;
|
||||||
|
short topname;
|
||||||
|
short nsname;
|
||||||
|
char *domain;
|
||||||
|
int domain_len;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
memset(buf, 0, buflen);
|
||||||
|
|
||||||
|
header = (HEADER*)buf;
|
||||||
|
|
||||||
|
header->id = htons(q->id);
|
||||||
|
header->qr = 1;
|
||||||
|
header->opcode = 0;
|
||||||
|
header->aa = 1;
|
||||||
|
header->tc = 0;
|
||||||
|
header->rd = 0;
|
||||||
|
header->ra = 0;
|
||||||
|
|
||||||
|
p = buf + sizeof(HEADER);
|
||||||
|
|
||||||
|
header->qdcount = htons(1);
|
||||||
|
header->ancount = htons(1);
|
||||||
|
header->arcount = htons(1);
|
||||||
|
|
||||||
|
/* pointer to start of name */
|
||||||
|
name = 0xc000 | ((p - buf) & 0x3fff);
|
||||||
|
|
||||||
|
domain = strstr(q->name, topdomain);
|
||||||
|
if (domain) {
|
||||||
|
domain_len = (int) (domain - q->name);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* pointer to start of topdomain */
|
||||||
|
topname = 0xc000 | ((p - buf + domain_len) & 0x3fff);
|
||||||
|
|
||||||
|
/* Query section */
|
||||||
|
putname(&p, sizeof(q->name), q->name); /* Name */
|
||||||
|
putshort(&p, q->type); /* Type */
|
||||||
|
putshort(&p, C_IN); /* Class */
|
||||||
|
|
||||||
|
/* Answer section */
|
||||||
|
putshort(&p, name); /* Name */
|
||||||
|
putshort(&p, q->type); /* Type */
|
||||||
|
putshort(&p, C_IN); /* Class */
|
||||||
|
putlong(&p, 0x3ea7d011); /* TTL */
|
||||||
|
putshort(&p, 5); /* Data length */
|
||||||
|
|
||||||
|
/* pointer to ns.topdomain */
|
||||||
|
nsname = 0xc000 | ((p - buf) & 0x3fff);
|
||||||
|
putbyte(&p, 2);
|
||||||
|
putbyte(&p, 'n');
|
||||||
|
putbyte(&p, 's');
|
||||||
|
putshort(&p, topname); /* Name Server */
|
||||||
|
|
||||||
|
/* Additional data (A-record of NS server) */
|
||||||
|
putshort(&p, nsname); /* Name Server */
|
||||||
|
putshort(&p, T_A); /* Type */
|
||||||
|
putshort(&p, C_IN); /* Class */
|
||||||
|
putlong(&p, 0x3ea7d011); /* TTL */
|
||||||
|
putshort(&p, 4); /* Data length */
|
||||||
|
|
||||||
|
/* ugly hack to output IP address */
|
||||||
|
domain = (char *) &q->destination;
|
||||||
|
putbyte(&p, *domain++);
|
||||||
|
putbyte(&p, *domain++);
|
||||||
|
putbyte(&p, *domain++);
|
||||||
|
putbyte(&p, *domain);
|
||||||
|
|
||||||
|
len = p - buf;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
short
|
short
|
||||||
dns_get_id(char *packet, size_t packetlen)
|
dns_get_id(char *packet, size_t packetlen)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,7 @@ typedef enum {
|
||||||
} qr_t;
|
} qr_t;
|
||||||
|
|
||||||
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
|
int dns_encode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||||
|
int dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain);
|
||||||
short dns_get_id(char *packet, size_t packetlen);
|
short dns_get_id(char *packet, size_t packetlen);
|
||||||
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
int dns_decode(char *, size_t, struct query *, qr_t, char *, size_t);
|
||||||
|
|
||||||
|
|
|
@ -333,6 +333,19 @@ handle_null_request(int tun_fd, int dns_fd, struct query *q, int domain_len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_ns_request(int dns_fd, struct query *q)
|
||||||
|
{
|
||||||
|
char buf[64*1024];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = dns_encode_ns_response(buf, sizeof(buf), q, topdomain);
|
||||||
|
|
||||||
|
if (sendto(dns_fd, buf, len, 0, (struct sockaddr*)&q->from, q->fromlen) <= 0) {
|
||||||
|
warn("ns reply send error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
forward_query(int bind_fd, struct query *q)
|
forward_query(int bind_fd, struct query *q)
|
||||||
{
|
{
|
||||||
|
@ -443,6 +456,9 @@ tunnel_dns(int tun_fd, int dns_fd, int bind_fd)
|
||||||
case T_NULL:
|
case T_NULL:
|
||||||
handle_null_request(tun_fd, dns_fd, &q, domain_len);
|
handle_null_request(tun_fd, dns_fd, &q, domain_len);
|
||||||
break;
|
break;
|
||||||
|
case T_NS:
|
||||||
|
handle_ns_request(dns_fd, &q);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue