update changelog
[debian/iodine.git] / tests / dns.c
1 /*
2  * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
3  * 2006-2009 Bjorn Andersson <flex@kryo.se>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 #include <check.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <sys/stat.h>
27 #include <arpa/nameser.h>
28 #ifdef DARWIN
29 #define BIND_8_COMPAT
30 #include <arpa/nameser_compat.h>
31 #endif
32
33 #include "common.h"
34 #include "dns.h"
35 #include "encoding.h"
36 #include "base32.h"
37 #include "test.h"
38
39 static void dump_packet(char *, size_t);
40
41 static char query_packet[] =
42         "\x05\x39\x01\x00\x00\x01\x00\x00\x00\x00\x00\x01\x2D\x41\x6A\x62\x63"
43         "\x75\x79\x74\x63\x70\x65\x62\x30\x67\x71\x30\x6C\x74\x65\x62\x75\x78"
44         "\x67\x69\x64\x75\x6E\x62\x73\x73\x61\x33\x64\x66\x6F\x6E\x30\x63\x61"
45         "\x7A\x64\x62\x6F\x72\x71\x71\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00"
46         "\x0A\x00\x01\x00\x00\x29\x10\x00\x00\x00\x80\x00\x00\x00";
47
48 static char answer_packet[] =
49         "\x05\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
50         "\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
51         "\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
52         "\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20"
53         "\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
54         "\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
55
56 static char answer_packet_high_trans_id[] =
57         "\x85\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x05\x73\x69\x6C\x6C"
58         "\x79\x04\x68\x6F\x73\x74\x02\x6F\x66\x06\x69\x6F\x64\x69\x6E\x65\x04"
59         "\x63\x6F\x64\x65\x04\x6B\x72\x79\x6F\x02\x73\x65\x00\x00\x0A\x00\x01"
60         "\xC0\x0C\x00\x0A\x00\x01\x00\x00\x00\x00\x00\x23\x74\x68\x69\x73\x20"
61         "\x69\x73\x20\x74\x68\x65\x20\x6D\x65\x73\x73\x61\x67\x65\x20\x74\x6F"
62         "\x20\x62\x65\x20\x64\x65\x6C\x69\x76\x65\x72\x65\x64";
63 static char *msgData = "this is the message to be delivered";
64 static char *topdomain = "kryo.se";
65
66 static char *innerData = "HELLO this is the test data";
67
68 START_TEST(test_encode_query)
69 {
70         char buf[512];
71         char resolv[512];
72         struct query q;
73         struct encoder *enc;
74         char *d;
75         size_t len;
76         size_t enclen;
77         int ret;
78
79         enclen = sizeof(resolv);
80         memset(&buf, 0, sizeof(buf));
81         memset(&resolv, 0, sizeof(resolv));
82         memset(&q, 0, sizeof(struct query));
83         q.type = T_NULL;
84         q.id = 1337;
85         d = resolv;
86         enc = get_base32_encoder();
87
88         *d++ = 'A';
89         enc->encode(d, &enclen, innerData, strlen(innerData));
90         d = resolv + strlen(resolv);
91         if (*d != '.') {
92                 *d++ = '.';
93         }
94         strcpy(d, topdomain);
95         len = sizeof(buf);
96         ret = dns_encode(buf, len, &q, QR_QUERY, resolv, strlen(resolv));
97         len = sizeof(query_packet) - 1; /* Skip extra null character */
98
99         if (strncmp(query_packet, buf, sizeof(query_packet)) || ret != len) {
100                 printf("\n");
101                 dump_packet(query_packet, len);
102                 dump_packet(buf, ret);
103         }
104         fail_unless(strncmp(query_packet, buf, sizeof(query_packet)) == 0, "Did not compile expected packet");
105         fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
106 }
107 END_TEST
108
109 START_TEST(test_decode_query)
110 {
111         char buf[512];
112         char *domain;
113         struct query q;
114         struct encoder *enc;
115         size_t len;
116
117         memset(&q, 0, sizeof(struct query));
118         memset(&buf, 0, sizeof(buf));
119         q.id = 0;
120         len = sizeof(query_packet) - 1;
121         enc = get_base32_encoder();
122
123         dns_decode(buf, sizeof(buf), &q, QR_QUERY, query_packet, len);
124         domain = strstr(q.name, topdomain);
125         len = sizeof(buf);
126         unpack_data(buf, len, &(q.name[1]), (int) (domain - q.name) - 1, enc);
127
128         fail_unless(strncmp(buf, innerData, strlen(innerData)) == 0, "Did not extract expected host: '%s'", buf);
129         fail_unless(strlen(buf) == strlen(innerData), "Bad host length: %d, expected %d: '%s'", strlen(buf), strlen(innerData), buf);
130 }
131 END_TEST
132
133 START_TEST(test_encode_response)
134 {
135         char buf[512];
136         char *host = "silly.host.of.iodine.code.kryo.se";
137         struct query q;
138         int len;
139         int ret;
140
141         len = sizeof(buf);
142         memset(&buf, 0, sizeof(buf));
143         memset(&q, 0, sizeof(struct query));
144         strncpy(q.name, host, strlen(host));
145         q.type = T_NULL;
146         q.id = 1337;
147
148         ret = dns_encode(buf, len, &q, QR_ANSWER, msgData, strlen(msgData));
149         len = sizeof(answer_packet) - 1; /* Skip extra null character */
150
151         fail_unless(strncmp(answer_packet, buf, sizeof(answer_packet)) == 0, "Did not compile expected packet");
152         fail_unless(ret == len, "Bad packet length: %d, expected %d", ret, len);
153 }
154 END_TEST
155
156 START_TEST(test_decode_response)
157 {
158         char buf[512];
159         struct query q;
160         int len;
161         int ret;
162
163         len = sizeof(buf);
164         memset(&buf, 0, sizeof(buf));
165
166         ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet, sizeof(answer_packet)-1);
167         fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
168         fail_unless(strncmp(msgData, buf, strlen(msgData)) == 0, "Did not extract expected data");
169         fail_unless(q.id == 0x0539);
170 }
171 END_TEST
172
173 START_TEST(test_decode_response_with_high_trans_id)
174 {
175         char buf[512];
176         struct query q;
177         int len;
178         int ret;
179
180         len = sizeof(buf);
181         memset(&buf, 0, sizeof(buf));
182
183         ret = dns_decode(buf, len, &q, QR_ANSWER, answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id)-1);
184         fail_unless(ret == strlen(msgData), "Bad data length: %d, expected %d", ret, strlen(msgData));
185         fail_unless(strncmp(msgData, buf, strlen(msgData)) == 0, "Did not extract expected data");
186         fail_unless(q.id == 0x8539, "q.id was %08X instead of %08X!", q.id, 0x8539);
187 }
188 END_TEST
189
190 START_TEST(test_get_id_short_packet)
191 {
192         char buf[5];
193         int len;
194         unsigned short id;
195
196         len = sizeof(buf);
197         memset(&buf, 5, sizeof(buf));
198
199         id = dns_get_id(buf, len);
200         fail_unless(id == 0);
201 }
202 END_TEST
203
204 START_TEST(test_get_id_low)
205 {
206         unsigned short id;
207
208         id = dns_get_id(answer_packet, sizeof(answer_packet));
209         fail_unless(id == 1337);
210 }
211 END_TEST
212
213 START_TEST(test_get_id_high)
214 {
215         unsigned short id;
216
217         id = dns_get_id(answer_packet_high_trans_id, sizeof(answer_packet_high_trans_id));
218         fail_unless(id == 0x8539);
219 }
220 END_TEST
221
222 static void
223 dump_packet(char *buf, size_t len)
224 {
225         int pos;
226
227         for (pos = 0; pos < len; pos++) {
228                 printf("\\x%02X", (unsigned char) buf[pos]);
229         }
230         printf("\n");
231         for (pos = 0; pos < len; pos++) {
232                 if (isalnum((unsigned char) buf[pos])) {
233                         printf(" %c  ", (unsigned char) buf[pos]);
234                 } else {
235                         printf("    ");
236                 }
237         }
238         printf("\n");
239 }
240
241 TCase *
242 test_dns_create_tests()
243 {
244         TCase *tc;
245
246         tc = tcase_create("Dns");
247         tcase_add_test(tc, test_encode_query);
248         tcase_add_test(tc, test_decode_query);
249         tcase_add_test(tc, test_encode_response);
250         tcase_add_test(tc, test_decode_response);
251         tcase_add_test(tc, test_decode_response_with_high_trans_id);
252         tcase_add_test(tc, test_get_id_short_packet);
253         tcase_add_test(tc, test_get_id_low);
254         tcase_add_test(tc, test_get_id_high);
255
256         return tc;
257 }