Update connman settings for single device as well
[platform/upstream/connman.git] / tools / dnsproxy-test.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <arpa/inet.h>
32 #include <netinet/in.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netdb.h>
36 #include <resolv.h>
37 #include <glib.h>
38 #include <fcntl.h>
39
40 #if 0
41 #define DEBUG
42 #endif
43 #ifdef DEBUG
44 #include <stdio.h>
45
46 #define LOG(fmt, arg...) do { \
47         fprintf(stdout, "%s:%s() " fmt "\n",   \
48                         __FILE__, __func__ , ## arg); \
49 } while (0)
50 #else
51 #define LOG(fmt, arg...)
52 #endif
53
54 static unsigned char msg[] = {
55         0x00, 0x1c, /* len 28 */
56         0x31, 0x82, /* tran id */
57         0x01, 0x00, /* flags (recursion required) */
58         0x00, 0x01, /* questions (1) */
59         0x00, 0x00, /* answer rr */
60         0x00, 0x00, /* authority rr */
61         0x00, 0x00, /* additional rr */
62         0x06, 0x6c, 0x6f, 0x6c, 0x67, 0x65, 0x30, /* lolge0, just some name */
63         0x03, 0x63, 0x6f, 0x6d, /* com */
64         0x00,       /* null terminator */
65         0x00, 0x01, /* type A */
66         0x00, 0x01, /* class IN */
67 };
68
69 static unsigned char msg2[] = {
70         0x00, 0x1c, /* len 28 */
71         0x31, 0x83, /* tran id */
72         0x01, 0x00, /* flags (recursion required) */
73         0x00, 0x01, /* questions (1) */
74         0x00, 0x00, /* answer rr */
75         0x00, 0x00, /* authority rr */
76         0x00, 0x00, /* additional rr */
77         0x06, 0x6c, 0x6f, 0x67, 0x6c, 0x67, 0x65, /* loelge */
78         0x03, 0x63, 0x6f, 0x6d, /* com */
79         0x00,       /* null terminator */
80         0x00, 0x01, /* type A */
81         0x00, 0x01, /* class IN */
82
83         0x00, 0x1c, /* len 28 */
84         0x31, 0x84, /* tran id */
85         0x01, 0x00, /* flags (recursion required) */
86         0x00, 0x01, /* questions (1) */
87         0x00, 0x00, /* answer rr */
88         0x00, 0x00, /* authority rr */
89         0x00, 0x00, /* additional rr */
90         0x06, 0x6c, 0x6f, 0x67, 0x6c, 0x67, 0x65, /* loelge */
91         0x03, 0x6e, 0x65, 0x74, /* net */
92         0x00,       /* null terminator */
93         0x00, 0x01, /* type A */
94         0x00, 0x01, /* class IN */
95 };
96
97 static unsigned char msg_invalid[] = {
98         0x00, 0x1c, /* len 28 */
99         0x31, 0xC0, /* tran id */
100 };
101
102 static int create_tcp_socket(int family)
103 {
104         int sk, err;
105
106         sk = socket(family, SOCK_STREAM, IPPROTO_TCP);
107         if (sk < 0) {
108                 err = errno;
109                 LOG("Failed to create TCP socket %d/%s", err, strerror(err));
110                 return -err;
111         }
112
113         return sk;
114 }
115
116 static int create_udp_socket(int family)
117 {
118         int sk, err;
119
120         sk = socket(family, SOCK_DGRAM, IPPROTO_UDP);
121         if (sk < 0) {
122                 err = errno;
123                 LOG("Failed to create UDP socket %d/%s", err, strerror(err));
124                 return -err;
125         }
126
127         return sk;
128 }
129
130 static int connect_tcp_socket(char *server)
131 {
132         int sk;
133         int err = 0;
134
135         struct addrinfo hints, *rp;
136
137         memset(&hints, 0, sizeof(hints));
138
139         hints.ai_socktype = SOCK_STREAM;
140         hints.ai_family = AF_UNSPEC;
141         hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST;
142         getaddrinfo(server, "53", &hints, &rp);
143
144         sk = create_tcp_socket(rp->ai_family);
145         err = sk;
146
147         LOG("sk %d family %d", sk, rp->ai_family);
148
149         if (sk >= 0 && connect(sk, rp->ai_addr, rp->ai_addrlen) < 0) {
150                 err = -errno;
151                 close(sk);
152                 sk = -1;
153
154                 fprintf(stderr, "Failed to connect to DNS server at %s "
155                                 "errno %d/%s\n",
156                         server, -err, strerror(-err));
157         }
158
159         if (sk >= 0)
160                 fcntl(sk, F_SETFL, O_NONBLOCK);
161
162         freeaddrinfo(rp);
163
164         return err;
165 }
166
167 static int send_msg(int sk, unsigned char *msg, unsigned int len,
168                 int sleep_between)
169 {
170         unsigned int i;
171         int err;
172
173         for (i = 0; i < len; i++) {
174                 err = write(sk, &msg[i], 1);
175                 if (err < 0) {
176                         err = -errno;
177                         LOG("write failed errno %d/%s", -err, strerror(-err));
178                 }
179
180                 g_assert_cmpint(err, >=, 0);
181                 if (err < 0)
182                         return err;
183
184                 if (sleep_between)
185                         usleep(1000);
186         }
187
188         return 0;
189 }
190
191 static int connect_udp_socket(char *server, struct sockaddr *sa,
192                                                         socklen_t *sa_len)
193 {
194         int sk;
195         int err = 0;
196
197         struct addrinfo hints, *rp;
198
199         memset(&hints, 0, sizeof(hints));
200
201         hints.ai_socktype = SOCK_DGRAM;
202         hints.ai_family = AF_UNSPEC;
203         hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST;
204         getaddrinfo(server, "53", &hints, &rp);
205
206         sk = create_udp_socket(rp->ai_family);
207         err = sk;
208
209         LOG("sk %d family %d", sk, rp->ai_family);
210
211         if (sk < 0) {
212                 err = -errno;
213                 fprintf(stderr, "Failed to connect to DNS server at %s "
214                                 "errno %d/%s\n",
215                         server, -err, strerror(-err));
216         } else {
217                 memcpy(sa, rp->ai_addr, *sa_len);
218                 *sa_len = rp->ai_addrlen;
219         }
220
221         freeaddrinfo(rp);
222
223         return err;
224 }
225
226 static int sendto_msg(int sk, struct sockaddr *sa, socklen_t salen,
227                 unsigned char *msg, unsigned int len)
228 {
229         int err;
230
231         err = sendto(sk, msg, len, MSG_NOSIGNAL, sa, salen);
232         if (err < 0) {
233                 err = -errno;
234                 LOG("sendto failed errno %d/%s", -err, strerror(-err));
235         }
236
237         g_assert_cmpint(err, >=, 0);
238         if (err < 0)
239                 return err;
240
241         return 0;
242 }
243
244 static unsigned short get_id(void)
245 {
246         return random();
247 }
248
249 static void change_msg(unsigned char *msg, unsigned int tranid,
250                 unsigned int host_loc, unsigned char host_count)
251 {
252         unsigned short id = get_id();
253
254         msg[tranid] = id >> 8;
255         msg[tranid+1] = id;
256         msg[host_loc] = host_count;
257 }
258
259 static void change_msg2(unsigned char *msg, unsigned char host_count)
260 {
261         change_msg(msg, 2, 20, host_count);
262         change_msg(msg, 32, 50, host_count+1);
263 }
264
265 static int receive_message(int sk, int timeout, int expected, int *server_closed)
266 {
267         int ret, received = 0;
268         unsigned char buf[512];
269
270         while (timeout > 0) {
271                 ret = read(sk, buf, sizeof(buf));
272                 if (ret > 0) {
273                         LOG("received %d bytes from server %d", ret, sk);
274                         received += ret;
275                         if (received >= expected)
276                                 break;
277                 } else if (ret == 0) {
278                         LOG("server %d closed socket", sk);
279                         if (server_closed)
280                                 *server_closed = 1;
281                         break;
282                 } else {
283                         if (errno != EAGAIN && errno != EWOULDBLOCK)
284                                 break;
285                 }
286
287                 sleep(1);
288                 timeout--;
289         }
290
291         return received;
292 }
293
294 static int receive_from_message(int sk, struct sockaddr *sa, socklen_t len,
295                                 int timeout, int expected)
296 {
297         int ret, received = 0;
298         unsigned char buf[512];
299
300         fcntl(sk, F_SETFL, O_NONBLOCK);
301
302         while (timeout > 0) {
303                 ret = recvfrom(sk, buf, sizeof(buf), 0, sa, &len);
304                 if (ret > 0) {
305                         LOG("received %d bytes from server %d", ret, sk);
306                         received += ret;
307                         if (received >= expected)
308                                 break;
309                 } else if (ret < 0) {
310                         if (errno != EAGAIN && errno != EWOULDBLOCK)
311                                 break;
312                 }
313
314                 sleep(1);
315                 timeout--;
316         }
317
318         return received;
319 }
320
321 static void test_ipv4_udp_msg(void)
322 {
323         int sk, received = 0;
324         struct sockaddr_in sa;
325         socklen_t len = sizeof(sa);
326
327         sk = connect_udp_socket("127.0.0.1", (struct sockaddr *)&sa, &len);
328         g_assert_cmpint(sk, >=, 0);
329         change_msg(msg, 2, 20, '1');
330         sendto_msg(sk, (struct sockaddr *)&sa, len, msg, sizeof(msg));
331         received = receive_from_message(sk, (struct sockaddr *)&sa, len,
332                                         10, sizeof(msg));
333         close(sk);
334
335         g_assert_cmpint(received, >=, sizeof(msg));
336 }
337
338 static void test_ipv6_udp_msg(void)
339 {
340         int sk, received = 0;
341         struct sockaddr_in6 sa;
342         socklen_t len = sizeof(sa);
343
344         sk = connect_udp_socket("::1", (struct sockaddr *)&sa, &len);
345         g_assert_cmpint(sk, >=, 0);
346         change_msg(msg, 2, 20, '1');
347         sendto_msg(sk, (struct sockaddr *)&sa, len, msg, sizeof(msg));
348         received = receive_from_message(sk, (struct sockaddr *)&sa, len,
349                                         10, sizeof(msg));
350         close(sk);
351
352         g_assert_cmpint(received, >=, sizeof(msg));
353 }
354
355 static void test_partial_ipv4_tcp_msg(void)
356 {
357         int sk, received = 0;
358
359         sk = connect_tcp_socket("127.0.0.1");
360         g_assert_cmpint(sk, >=, 0);
361         change_msg(msg, 2, 20, '1');
362         send_msg(sk, msg, sizeof(msg), 1);
363         received = receive_message(sk, 10, sizeof(msg), NULL);
364         close(sk);
365
366         g_assert_cmpint(received, >=, sizeof(msg));
367 }
368
369 static void test_partial_ipv6_tcp_msg(void)
370 {
371         int sk, received = 0;
372
373         sk = connect_tcp_socket("::1");
374         g_assert_cmpint(sk, >=, 0);
375         change_msg(msg, 2, 20, '2');
376         send_msg(sk, msg, sizeof(msg), 1);
377         received = receive_message(sk, 10, sizeof(msg), NULL);
378         close(sk);
379
380         g_assert_cmpint(received, >=, sizeof(msg));
381 }
382
383 static void test_multiple_ipv4_tcp_msg(void)
384 {
385         int sk, received = 0, server_closed = 0;
386
387         sk = connect_tcp_socket("127.0.0.1");
388         g_assert_cmpint(sk, >=, 0);
389         change_msg2(msg2, '1');
390         send_msg(sk, msg2, sizeof(msg2), 0);
391         received = receive_message(sk, 35, sizeof(msg2), &server_closed);
392         close(sk);
393
394         /* If the final DNS server refuses to serve us, then do not consider
395          * it an error. This happens very often with unbound.
396          */
397         if (server_closed == 0)
398                 g_assert_cmpint(received, >=, sizeof(msg2));
399 }
400
401 static void test_multiple_ipv6_tcp_msg(void)
402 {
403         int sk, received = 0, server_closed = 0;
404
405         sk = connect_tcp_socket("::1");
406         g_assert_cmpint(sk, >=, 0);
407         change_msg2(msg2, '2');
408         send_msg(sk, msg2, sizeof(msg2), 0);
409         received = receive_message(sk, 35, sizeof(msg2), &server_closed);
410         close(sk);
411
412         if (server_closed == 0)
413                 g_assert_cmpint(received, >=, sizeof(msg2));
414 }
415
416 static void test_failure_tcp_msg(void)
417 {
418         int sk, received = 0;
419
420         sk = connect_tcp_socket("127.0.0.1");
421         g_assert_cmpint(sk, >=, 0);
422         send_msg(sk, msg_invalid, sizeof(msg_invalid), 0);
423         received = receive_message(sk, 10, 0, NULL);
424         close(sk);
425
426         g_assert_cmpint(received, ==, 0);
427 }
428
429 int main(int argc, char *argv[])
430 {
431         g_test_init(&argc, &argv, NULL);
432
433         g_test_add_func("/dnsproxy/ipv4 udp msg",
434                         test_ipv4_udp_msg);
435
436         g_test_add_func("/dnsproxy/ipv6 udp msg",
437                         test_ipv6_udp_msg);
438
439         g_test_add_func("/dnsproxy/failure tcp msg ",
440                         test_failure_tcp_msg);
441
442         g_test_add_func("/dnsproxy/partial ipv4 tcp msg",
443                         test_partial_ipv4_tcp_msg);
444
445         g_test_add_func("/dnsproxy/partial ipv6 tcp msg",
446                         test_partial_ipv6_tcp_msg);
447
448         g_test_add_func("/dnsproxy/partial ipv4 tcp msg from cache",
449                         test_partial_ipv4_tcp_msg);
450
451         g_test_add_func("/dnsproxy/partial ipv6 tcp msg from cache",
452                         test_partial_ipv6_tcp_msg);
453
454         g_test_add_func("/dnsproxy/multiple ipv4 tcp msg",
455                         test_multiple_ipv4_tcp_msg);
456
457         g_test_add_func("/dnsproxy/multiple ipv6 tcp msg",
458                         test_multiple_ipv6_tcp_msg);
459
460         g_test_add_func("/dnsproxy/multiple ipv4 tcp msg from cache",
461                         test_multiple_ipv4_tcp_msg);
462
463         g_test_add_func("/dnsproxy/multiple ipv6 tcp msg from cache",
464                         test_multiple_ipv6_tcp_msg);
465
466         return g_test_run();
467 }