2 * Copyright (c) 2006-2009 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 <arpa/inet.h>
18 #include <arpa/nameser.h>
20 #include <arpa/nameser8_compat.h>
36 dns_encode(char *buf, size_t buflen, struct query *q, qr_t qr, char *data, size_t datalen)
43 memset(buf, 0, buflen);
45 header = (HEADER*)buf;
47 header->id = htons(q->id);
48 header->qr = (qr == QR_ANSWER);
50 header->aa = (qr == QR_ANSWER);
52 header->rd = (qr == QR_QUERY);
55 p = buf + sizeof(HEADER);
59 header->ancount = htons(1);
60 header->qdcount = htons(1);
62 name = 0xc000 | ((p - buf) & 0x3fff);
64 putname(&p, sizeof(q->name), q->name);
66 putshort(&p, q->type);
70 putshort(&p, q->type);
74 putshort(&p, datalen);
75 putdata(&p, data, datalen);
78 header->qdcount = htons(1);
79 header->arcount = htons(1);
81 putname(&p, datalen, data);
83 putshort(&p, q->type);
87 putbyte(&p, 0x00); /* Root */
88 putshort(&p, 0x0029); /* OPT */
89 putshort(&p, 0x1000); /* Payload size: 4096 */
90 putshort(&p, 0x0000); /* Higher bits/edns version */
91 putshort(&p, 0x8000); /* Z */
92 putshort(&p, 0x0000); /* Data length */
102 dns_encode_ns_response(char *buf, size_t buflen, struct query *q, char *topdomain)
113 memset(buf, 0, buflen);
115 header = (HEADER*)buf;
117 header->id = htons(q->id);
125 p = buf + sizeof(HEADER);
127 header->qdcount = htons(1);
128 header->ancount = htons(1);
129 header->arcount = htons(1);
131 /* pointer to start of name */
132 name = 0xc000 | ((p - buf) & 0x3fff);
134 domain = strstr(q->name, topdomain);
136 domain_len = (int) (domain - q->name);
140 /* pointer to start of topdomain */
141 topname = 0xc000 | ((p - buf + domain_len) & 0x3fff);
144 putname(&p, sizeof(q->name), q->name); /* Name */
145 putshort(&p, q->type); /* Type */
146 putshort(&p, C_IN); /* Class */
149 putshort(&p, name); /* Name */
150 putshort(&p, q->type); /* Type */
151 putshort(&p, C_IN); /* Class */
152 putlong(&p, 0x3ea7d011); /* TTL */
153 putshort(&p, 5); /* Data length */
155 /* pointer to ns.topdomain */
156 nsname = 0xc000 | ((p - buf) & 0x3fff);
160 putshort(&p, topname); /* Name Server */
162 /* Additional data (A-record of NS server) */
163 putshort(&p, nsname); /* Name Server */
164 putshort(&p, T_A); /* Type */
165 putshort(&p, C_IN); /* Class */
166 putlong(&p, 0x3ea7d011); /* TTL */
167 putshort(&p, 4); /* Data length */
169 /* ugly hack to output IP address */
170 domain = (char *) &q->destination;
171 putbyte(&p, *domain++);
172 putbyte(&p, *domain++);
173 putbyte(&p, *domain++);
174 putbyte(&p, *domain);
181 dns_get_id(char *packet, size_t packetlen)
184 header = (HEADER*)packet;
186 if (packetlen < sizeof(HEADER))
189 return ntohs(header->id);
193 dns_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen)
195 char name[QUERY_NAME_SIZE];
209 header = (HEADER*)packet;
211 /* Reject short packets */
212 if (packetlen < sizeof(HEADER))
215 if (header->qr != qr) {
216 warnx("header->qr does not match the requested qr");
220 data = packet + sizeof(HEADER);
221 qdcount = ntohs(header->qdcount);
222 ancount = ntohs(header->ancount);
224 id = ntohs(header->id);
225 id = id & 0xFFFF; /* Kill any sign extension */
231 if(qdcount != 1 || ancount != 1) {
232 switch (header->rcode) {
234 warnx("Got REFUSED as reply");
238 warnx("Got NOTIMP as reply");
242 warnx("Got NXDOMAIN as reply");
246 warnx("Got SERVFAIL as reply");
251 warnx("no query or answer in reply packet");
260 readname(packet, packetlen, &data, name, sizeof(name));
261 readshort(packet, &data, &type);
262 readshort(packet, &data, &class);
264 readname(packet, packetlen, &data, name, sizeof(name));
265 readshort(packet, &data, &type);
266 readshort(packet, &data, &class);
267 readlong(packet, &data, &ttl);
268 readshort(packet, &data, &rlen);
269 rv = MIN(rlen, sizeof(rdata));
270 rv = readdata(packet, &data, rdata, rv);
272 if(type == T_NULL && rv >= 2 && buf) {
273 rv = MIN(rv, buflen);
274 memcpy(buf, rdata, rv);
279 warnx("no question section in name query");
283 readname(packet, packetlen, &data, name, sizeof(name) - 1);
284 name[sizeof(name)-1] = '\0';
285 readshort(packet, &data, &type);
286 readshort(packet, &data, &class);
288 strncpy(q->name, name, sizeof(q->name));
289 q->name[sizeof(q->name) - 1] = '\0';
293 rv = strlen(q->name);