e42b8a4ac8dbdd515fb1ab55fd07d03d4f5c1e39
[resolv_wrapper.git] / tests / test_res_init.c
1 #include "config.h"
2
3 #include <stdarg.h>
4 #include <stddef.h>
5 #include <setjmp.h>
6 #include <cmocka.h>
7
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdio.h>
12
13 #include <netinet/in.h>
14 #include <arpa/nameser.h>
15 #include <arpa/inet.h>
16 #include <resolv.h>
17
18 #define RWRAP_RESOLV_CONF_TMPL "rwrap_resolv_conf_XXXXXX"
19
20 struct resolv_conf_test_state {
21         int rc_fd;
22         FILE *resolv_conf;
23         char *resolv_conf_path;
24 };
25
26 static void setup(void **state)
27 {
28         struct resolv_conf_test_state *test_state;
29
30         test_state = malloc(sizeof(struct resolv_conf_test_state));
31         assert_non_null(test_state);
32         test_state->rc_fd = -1;
33         test_state->resolv_conf = NULL;
34
35         test_state->resolv_conf_path = strdup(RWRAP_RESOLV_CONF_TMPL);
36         assert_non_null(test_state->resolv_conf_path);
37         test_state->rc_fd = mkstemp(test_state->resolv_conf_path);
38         assert_non_null(test_state->resolv_conf_path);
39         test_state->resolv_conf = fdopen(test_state->rc_fd, "a");
40         assert_non_null(test_state->resolv_conf);
41
42         *state = test_state;
43 }
44
45 static void teardown(void **state)
46 {
47         struct resolv_conf_test_state *test_state;
48
49         test_state = (struct resolv_conf_test_state *) *state;
50
51         if (test_state == NULL) return;
52
53         if (test_state->resolv_conf) {
54                 fclose(test_state->resolv_conf);
55         }
56
57         if (test_state->rc_fd != -1) {
58                 close(test_state->rc_fd);
59         }
60
61         if (test_state->resolv_conf_path) {
62                 unlink(test_state->resolv_conf_path);
63                 free(test_state->resolv_conf_path);
64         }
65
66         free(test_state);
67 }
68
69 static void test_res_ninit(void **state)
70 {
71         struct resolv_conf_test_state *test_state;
72         struct __res_state dnsstate;
73         /*
74          * libc resolver only supports 3 name servers. Make sure the
75          * extra are skipped for both v4 and v6. Also make sure there's
76          * 'too many' nameservers even on platforms where v6 is not
77          * supported.
78          */
79         const char *nameservers[] = {
80                 "127.0.0.1",
81                 "10.10.10.1",
82                 "2607:f8b0:4009:802::1011",
83                 "10.10.10.2",
84                 "10.10.10.3",
85                 "2607:f8b0:4009:802::1012",
86                 NULL,
87         };
88         int i;
89         int rv;
90         char straddr[INET6_ADDRSTRLEN] = { '\0' };
91 #ifdef HAVE_RESOLV_IPV6_NSADDRS
92         struct sockaddr_in6 *sa6;
93 #endif
94
95         test_state = (struct resolv_conf_test_state *) *state;
96
97         /*
98          * Write a valid resolv.conf.
99          * Make sure it's possible to skip comments
100          */
101         fputs("# Hello world\n", test_state->resolv_conf);
102         fputs("; This is resolv_wrapper\n", test_state->resolv_conf);
103         for (i = 0; nameservers[i]; i++) {
104                 fputs("nameserver ", test_state->resolv_conf);
105                 fputs(nameservers[i], test_state->resolv_conf);
106                 fputs("\n", test_state->resolv_conf);
107         }
108         fflush(test_state->resolv_conf);
109
110         rv = setenv("RESOLV_WRAPPER_CONF", test_state->resolv_conf_path, 1);
111         assert_int_equal(rv, 0);
112
113         memset(&dnsstate, 0, sizeof(dnsstate));
114         rv = res_ninit(&dnsstate);
115         unsetenv("RESOLV_WRAPPER_CONF");
116         assert_int_equal(rv, 0);
117
118         /*
119          * Validate the number of parsed name servers.
120          */
121
122         assert_int_equal(dnsstate.nscount + dnsstate._u._ext.nscount, MAXNS);
123
124 #ifndef HAVE_RESOLV_IPV6_NSADDRS
125         /*
126          * On platforms that don't support IPv6, the v6 address is skipped
127          * and we end up reading three v4 addresses.
128          */
129         assert_int_equal(dnsstate.nscount, MAXNS);
130 #else
131         /*
132          * test we have two v4 and one v6 server
133          *
134          * Note: This test assumes MAXNS == 3, which is the
135          * case on all systems encountered so far.
136          */
137         assert_int_equal(dnsstate.nscount, 2);
138         assert_int_equal(dnsstate._u._ext.nscount, 1);
139 #endif /* HAVE_RESOLV_IPV6_NSADDRS */
140
141         /* Validate the servers. */
142
143         /* IPv4 */
144         assert_int_equal(dnsstate.nsaddr_list[0].sin_family, AF_INET);
145         assert_int_equal(dnsstate.nsaddr_list[0].sin_port, htons(53));
146         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[0].sin_addr),
147                   straddr, INET6_ADDRSTRLEN);
148         assert_string_equal(nameservers[0], straddr);
149
150         assert_int_equal(dnsstate.nsaddr_list[1].sin_family, AF_INET);
151         assert_int_equal(dnsstate.nsaddr_list[1].sin_port, htons(53));
152         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[1].sin_addr),
153                   straddr, INET6_ADDRSTRLEN);
154         assert_string_equal(nameservers[1], straddr);
155
156 #ifndef HAVE_RESOLV_IPV6_NSADDRS
157         /*
158          * On platforms that don't support IPv6, the v6 address is skipped
159          * and we end up reading three v4 addresses.
160          */
161         assert_int_equal(dnsstate.nsaddr_list[2].sin_family, AF_INET);
162         assert_int_equal(dnsstate.nsaddr_list[2].sin_port, htons(53));
163         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[2].sin_addr),
164                   straddr, INET6_ADDRSTRLEN);
165         assert_string_equal(nameservers[3], straddr);
166 #else
167         /* IPv6 */
168         sa6 = dnsstate._u._ext.nsaddrs[0];
169         assert_int_equal(sa6->sin6_family, AF_INET6);
170         assert_int_equal(sa6->sin6_port, htons(53));
171         inet_ntop(AF_INET6, &(sa6->sin6_addr), straddr, INET6_ADDRSTRLEN);
172         assert_string_equal(nameservers[2], straddr);
173 #endif
174
175         res_nclose(&dnsstate);
176 }
177
178 static void test_res_ninit_enoent(void **state)
179 {
180         int rv;
181         struct __res_state dnsstate;
182
183         (void) state; /* unused */
184
185         rv = setenv("RESOLV_WRAPPER_CONF", "/no/such/file", 1);
186         assert_int_equal(rv, 0);
187
188         /* Just make sure we don't crash, error is fine */
189         memset(&dnsstate, 0, sizeof(dnsstate));
190         rv = res_ninit(&dnsstate);
191         unsetenv("RESOLV_WRAPPER_CONF");
192         assert_int_equal(rv, -1);
193 }
194
195 int main(void) {
196         int rc;
197
198         const UnitTest tests[] = {
199                 unit_test_setup_teardown(test_res_ninit, setup, teardown),
200                 unit_test(test_res_ninit_enoent),
201         };
202
203         rc = run_tests(tests);
204         return rc;
205 }