04ade89c58ef0a93524f90c5d9cac598fc82fc59
[resolv_wrapper.git] / tests / test_real_res_query.c
1 /*
2  * Copyright (C) Jakub Hrozek 2014 <jakub.hrozek@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <stdarg.h>
19 #include <stddef.h>
20 #include <setjmp.h>
21 #include <cmocka.h>
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <ctype.h>
30
31 #include <netinet/in.h>
32 #include <arpa/nameser.h>
33 #include <arpa/inet.h>
34 #include <resolv.h>
35
36 #ifndef MIN
37 #define MIN(a,b) ((a)<(b)?(a):(b))
38 #endif
39
40 #define ANSIZE 256
41
42 static void print_asc(const uint8_t *buf, uint32_t len)
43 {
44         uint32_t i;
45         for (i = 0; i < len; i++) {
46                 printf("%c", isprint(buf[i])?buf[i]:'.');
47         }
48 }
49
50 static void dump_data(const uint8_t *buf, int len)
51 {
52         int i=0;
53         static const uint8_t empty[16] = { 0, };
54
55         if (len<=0) return;
56
57         for (i=0; i<len;) {
58
59                 if (i%16 == 0) {
60                         if ((i > 0) &&
61                             (len > i+16) &&
62                             (memcmp(&buf[i], &empty, 16) == 0))
63                         {
64                                 i +=16;
65                                 continue;
66                         }
67
68                         if (i<len)  {
69                                 printf("[%04X] ",i);
70                         }
71                 }
72
73                 printf("%02x ", buf[i]);
74                 i++;
75
76                 if (i%8 == 0) printf("  ");
77                 if (i%16 == 0) {
78                         print_asc(&buf[i-16],8); printf(" ");
79                         print_asc(&buf[i-8],8); printf("\n");
80                 }
81         }
82
83         if (i%16) {
84                 int n;
85                 n = 16 - (i%16);
86                 printf(" ");
87                 if (n>8) printf(" ");
88                 while (n--) printf("   ");
89                 n = MIN(8,i%16);
90                 print_asc(&buf[i-(i%16)],n); printf( " " );
91                 n = (i%16) - n;
92                 if (n>0) print_asc(&buf[i-n],n);
93                 printf("\n");
94         }
95 }
96
97 static void test_res_query_a_record(void **state)
98 {
99         int rv;
100         struct __res_state dnsstate;
101         unsigned char answer[ANSIZE] = { 0 };
102         char addr[INET_ADDRSTRLEN];
103         ns_msg handle;
104         ns_rr rr;   /* expanded resource record */
105
106         (void) state; /* unused */
107
108         memset(&dnsstate, 0, sizeof(struct __res_state));
109         rv = res_ninit(&dnsstate);
110         assert_int_equal(rv, 0);
111
112         rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_a,
113                         answer, sizeof(answer));
114         assert_in_range(rv, 1, 100);
115
116         printf("dump answer:\n");
117         dump_data(answer, rv);
118
119         ns_initparse(answer, sizeof(answer), &handle);
120         /* The query must finish w/o an error, have one answer and the answer
121          * must be a parseable RR of type A and have the address that our
122          * fake hosts file contains
123          */
124         assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
125         assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
126         assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
127         assert_int_equal(ns_rr_type(rr), ns_t_a);
128         assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
129                         addr, sizeof(addr)));
130         assert_string_equal(addr, "78.46.80.163");
131 }
132
133 static void test_res_query_srv_record(void **state)
134 {
135         int rv;
136         struct __res_state dnsstate;
137         unsigned char answer[ANSIZE] = { 0 };
138         ns_msg handle;
139         ns_rr rr;   /* expanded resource record */
140         const uint8_t *rrdata;
141         int prio;
142         int weight;
143         int port;
144         char hostname[MAXDNAME];
145
146         (void) state; /* unused */
147
148         memset(&dnsstate, 0, sizeof(struct __res_state));
149         rv = res_ninit(&dnsstate);
150         assert_int_equal(rv, 0);
151
152         rv = res_nquery(&dnsstate, "_http._tcp.mxtoolbox.com", ns_c_in, ns_t_srv,
153                         answer, sizeof(answer));
154         assert_in_range(rv, 1, 100);
155
156         printf("dump answer:\n");
157         dump_data(answer, rv);
158
159         ns_initparse(answer, sizeof(answer), &handle);
160
161         /*
162          * The query must finish w/o an error, have one answer and the answer
163          * must be a parseable RR of type SRV and have the priority, weight,
164          * port and hostname as in the fake hosts file
165          */
166         assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
167         assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
168         assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
169         assert_int_equal(ns_rr_type(rr), ns_t_srv);
170
171         rrdata = ns_rr_rdata(rr);
172         NS_GET16(prio, rrdata);
173         NS_GET16(weight, rrdata);
174         NS_GET16(port, rrdata);
175
176         rv = ns_name_uncompress(ns_msg_base(handle),
177                                 ns_msg_end(handle),
178                                 rrdata,
179                                 hostname, MAXDNAME);
180         assert_int_not_equal(rv, -1);
181
182         assert_int_equal(prio, 10);
183         assert_int_equal(weight, 100);
184         assert_int_equal(port, 80);
185         assert_string_equal(hostname, "mxtoolbox.com");
186 }
187
188 int main(void)
189 {
190         int rc;
191
192         const struct CMUnitTest real_tests[] = {
193                 cmocka_unit_test(test_res_query_a_record),
194                 cmocka_unit_test(test_res_query_srv_record),
195         };
196
197         rc = cmocka_run_group_tests(real_tests, NULL, NULL);
198
199         return rc;
200 }