rwrap: Add NOTICE as log level
[resolv_wrapper.git] / tests / test_real_res_query.c
1 /*
2  * Copyright (C) Jakub Hrozek 2014 <jakub.hrozek@posteo.se>
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_ns_record(void **state)
134 {
135         int rv;
136         struct __res_state dnsstate;
137         unsigned char answer[ANSIZE] = { 0 };
138         char addr[INET_ADDRSTRLEN];
139         ns_msg handle;
140         ns_rr rr;   /* expanded resource record */
141
142         (void) state; /* unused */
143
144         memset(&dnsstate, 0, sizeof(struct __res_state));
145         rv = res_ninit(&dnsstate);
146         assert_int_equal(rv, 0);
147
148         rv = res_nquery(&dnsstate, "cwrap.org", ns_c_in, ns_t_ns,
149                         answer, sizeof(answer));
150         assert_in_range(rv, 1, 150);
151
152         printf("dump answer:\n");
153         dump_data(answer, rv);
154
155         ns_initparse(answer, sizeof(answer), &handle);
156         /* The query must finish w/o an error, have two answers and the answer
157          * must be a parseable RR of type A and have the address that our
158          * fake hosts file contains
159          */
160         assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
161         assert_int_equal(ns_msg_count(handle, ns_s_an), 2);
162         assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
163         assert_int_equal(ns_rr_type(rr), ns_t_ns);
164         assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr),
165                         addr, sizeof(addr)));
166         /*assert_string_equal(addr, "3.110.115.50");*/
167 }
168
169 static void test_res_query_srv_record(void **state)
170 {
171         int rv;
172         struct __res_state dnsstate;
173         unsigned char answer[ANSIZE] = { 0 };
174         ns_msg handle;
175         ns_rr rr;   /* expanded resource record */
176         const uint8_t *rrdata;
177         int prio;
178         int weight;
179         int port;
180         char hostname[MAXDNAME];
181
182         (void) state; /* unused */
183
184         memset(&dnsstate, 0, sizeof(struct __res_state));
185         rv = res_ninit(&dnsstate);
186         assert_int_equal(rv, 0);
187
188         rv = res_nquery(&dnsstate, "_http._tcp.mxtoolbox.com", ns_c_in, ns_t_srv,
189                         answer, sizeof(answer));
190         assert_in_range(rv, 1, 100);
191
192         printf("dump answer:\n");
193         dump_data(answer, rv);
194
195         ns_initparse(answer, sizeof(answer), &handle);
196
197         /*
198          * The query must finish w/o an error, have one answer and the answer
199          * must be a parseable RR of type SRV and have the priority, weight,
200          * port and hostname as in the fake hosts file
201          */
202         assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
203         assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
204         assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
205         assert_int_equal(ns_rr_type(rr), ns_t_srv);
206
207         rrdata = ns_rr_rdata(rr);
208         NS_GET16(prio, rrdata);
209         NS_GET16(weight, rrdata);
210         NS_GET16(port, rrdata);
211
212         rv = ns_name_uncompress(ns_msg_base(handle),
213                                 ns_msg_end(handle),
214                                 rrdata,
215                                 hostname, MAXDNAME);
216         assert_int_not_equal(rv, -1);
217
218         assert_int_equal(prio, 10);
219         assert_int_equal(weight, 100);
220         assert_int_equal(port, 80);
221         assert_string_equal(hostname, "mxtoolbox.com");
222 }
223
224 int main(void)
225 {
226         int rc;
227
228         const struct CMUnitTest real_tests[] = {
229                 cmocka_unit_test(test_res_query_a_record),
230                 cmocka_unit_test(test_res_query_ns_record),
231                 cmocka_unit_test(test_res_query_srv_record),
232         };
233
234         rc = cmocka_run_group_tests(real_tests, NULL, NULL);
235
236         return rc;
237 }