2 * Copyright (c) 2006-2007 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, 256, 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, 256, 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_decode(char *buf, size_t buflen, struct query *q, qr_t qr, char *packet, size_t packetlen)
118 header = (HEADER*)packet;
120 /* Reject short packets */
121 if (packetlen < sizeof(HEADER))
124 if (header->qr != qr) {
125 warnx("header->qr does not match the requested qr");
129 data = packet + sizeof(HEADER);
130 qdcount = ntohs(header->qdcount);
131 ancount = ntohs(header->ancount);
133 id = ntohs(header->id);
139 if(qdcount != 1 || ancount != 1) {
140 warnx("no query or answer in answer");
147 readname(packet, packetlen, &data, name, sizeof(name));
148 readshort(packet, &data, &type);
149 readshort(packet, &data, &class);
151 readname(packet, packetlen, &data, name, sizeof(name));
152 readshort(packet, &data, &type);
153 readshort(packet, &data, &class);
154 readlong(packet, &data, &ttl);
155 readshort(packet, &data, &rlen);
156 rv = MIN(rlen, sizeof(rdata));
157 rv = readdata(packet, &data, rdata, rv);
159 if(type == T_NULL && rv > 2) {
160 rv = MIN(rv, buflen);
161 memcpy(buf, rdata, rv);
166 warnx("no query on query");
170 readname(packet, packetlen, &data, name, sizeof(name) -1);
172 readshort(packet, &data, &type);
173 readshort(packet, &data, &class);
180 strncpy(q->name, name, 257);
184 rv = strlen(q->name);
192 dns_build_hostname(char *buf, size_t buflen,
193 const char *data, const size_t datalen,
194 const char *topdomain)
200 avail = MIN(0xFF, buflen) - strlen(topdomain) - 2;
201 memset(buf, 0, buflen);
204 consumed = encode_data(data, datalen, avail, b);
210 strncpy(b, topdomain, strlen(topdomain)+1);