tests/test_res_init.c: avoid using public ipv6 addresses from google in tests
[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 int 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         return 0;
45 }
46
47 static int teardown(void **state)
48 {
49         struct resolv_conf_test_state *test_state;
50
51         test_state = (struct resolv_conf_test_state *) *state;
52
53         if (test_state == NULL) return -1;
54
55         if (test_state->resolv_conf) {
56                 fclose(test_state->resolv_conf);
57         }
58
59         if (test_state->rc_fd != -1) {
60                 close(test_state->rc_fd);
61         }
62
63         if (test_state->resolv_conf_path) {
64                 unlink(test_state->resolv_conf_path);
65                 free(test_state->resolv_conf_path);
66         }
67
68         free(test_state);
69
70         return 0;
71 }
72
73 static void test_res_ninit(void **state)
74 {
75         struct resolv_conf_test_state *test_state;
76         struct __res_state dnsstate;
77         /*
78          * libc resolver only supports 3 name servers. Make sure the
79          * extra are skipped for both v4 and v6. Also make sure there's
80          * 'too many' nameservers even on platforms where v6 is not
81          * supported.
82          */
83         const char *nameservers[] = {
84                 "127.0.0.1",
85                 "10.10.10.1",
86                 "fd53:53:53:53::1011",
87                 "10.10.10.2",
88                 "10.10.10.3",
89                 "fd53:53:53:53::1012",
90                 NULL,
91         };
92         int i;
93         int rv;
94         char straddr[INET6_ADDRSTRLEN] = { '\0' };
95 #ifdef HAVE_RESOLV_IPV6_NSADDRS
96         struct sockaddr_in6 *sa6;
97 #endif
98
99         test_state = (struct resolv_conf_test_state *) *state;
100
101         /*
102          * Write a valid resolv.conf.
103          * Make sure it's possible to skip comments
104          */
105         fputs("# Hello world\n", test_state->resolv_conf);
106         fputs("; This is resolv_wrapper\n", test_state->resolv_conf);
107         for (i = 0; nameservers[i]; i++) {
108                 fputs("nameserver ", test_state->resolv_conf);
109                 fputs(nameservers[i], test_state->resolv_conf);
110                 fputs("\n", test_state->resolv_conf);
111         }
112         fflush(test_state->resolv_conf);
113
114         rv = setenv("RESOLV_WRAPPER_CONF", test_state->resolv_conf_path, 1);
115         assert_int_equal(rv, 0);
116
117         memset(&dnsstate, 0, sizeof(dnsstate));
118         rv = res_ninit(&dnsstate);
119         unsetenv("RESOLV_WRAPPER_CONF");
120         assert_int_equal(rv, 0);
121
122         /*
123          * Validate the number of parsed name servers.
124          */
125
126         assert_int_equal(dnsstate.nscount + dnsstate._u._ext.nscount, MAXNS);
127
128 #ifndef HAVE_RESOLV_IPV6_NSADDRS
129         /*
130          * On platforms that don't support IPv6, the v6 address is skipped
131          * and we end up reading three v4 addresses.
132          */
133         assert_int_equal(dnsstate.nscount, MAXNS);
134 #else
135         /*
136          * test we have two v4 and one v6 server
137          *
138          * Note: This test assumes MAXNS == 3, which is the
139          * case on all systems encountered so far.
140          */
141         assert_int_equal(dnsstate.nscount, 2);
142         assert_int_equal(dnsstate._u._ext.nscount, 1);
143 #endif /* HAVE_RESOLV_IPV6_NSADDRS */
144
145         /* Validate the servers. */
146
147         /* IPv4 */
148         assert_int_equal(dnsstate.nsaddr_list[0].sin_family, AF_INET);
149         assert_int_equal(dnsstate.nsaddr_list[0].sin_port, htons(53));
150         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[0].sin_addr),
151                   straddr, INET6_ADDRSTRLEN);
152         assert_string_equal(nameservers[0], straddr);
153
154         assert_int_equal(dnsstate.nsaddr_list[1].sin_family, AF_INET);
155         assert_int_equal(dnsstate.nsaddr_list[1].sin_port, htons(53));
156         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[1].sin_addr),
157                   straddr, INET6_ADDRSTRLEN);
158         assert_string_equal(nameservers[1], straddr);
159
160 #ifndef HAVE_RESOLV_IPV6_NSADDRS
161         /*
162          * On platforms that don't support IPv6, the v6 address is skipped
163          * and we end up reading three v4 addresses.
164          */
165         assert_int_equal(dnsstate.nsaddr_list[2].sin_family, AF_INET);
166         assert_int_equal(dnsstate.nsaddr_list[2].sin_port, htons(53));
167         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[2].sin_addr),
168                   straddr, INET6_ADDRSTRLEN);
169         assert_string_equal(nameservers[3], straddr);
170 #else
171         /* IPv6 */
172         sa6 = dnsstate._u._ext.nsaddrs[0];
173         assert_int_equal(sa6->sin6_family, AF_INET6);
174         assert_int_equal(sa6->sin6_port, htons(53));
175         inet_ntop(AF_INET6, &(sa6->sin6_addr), straddr, INET6_ADDRSTRLEN);
176         assert_string_equal(nameservers[2], straddr);
177 #endif
178
179         res_nclose(&dnsstate);
180 }
181
182 static void test_res_ninit_enoent(void **state)
183 {
184         int rv;
185         struct __res_state dnsstate;
186
187         (void) state; /* unused */
188
189         rv = setenv("RESOLV_WRAPPER_CONF", "/no/such/file", 1);
190         assert_int_equal(rv, 0);
191
192         /* Just make sure we don't crash, error is fine */
193         memset(&dnsstate, 0, sizeof(dnsstate));
194         rv = res_ninit(&dnsstate);
195         unsetenv("RESOLV_WRAPPER_CONF");
196         assert_int_equal(rv, -1);
197 }
198
199 int main(void) {
200         int rc;
201
202         const struct CMUnitTest init_tests[] = {
203                 cmocka_unit_test_setup_teardown(test_res_ninit, setup, teardown),
204                 cmocka_unit_test(test_res_ninit_enoent),
205         };
206
207         rc = cmocka_run_group_tests(init_tests, NULL, NULL);
208
209         return rc;
210 }