f0cd2ee6b116c0b1961458f1e062f2b773dce483
[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          * On platforms that don't support IPv6, the v6 address is skipped
126          * and we end up reading three v4 addresses.
127          *
128          * test we have two v4 and one v6 server
129          *
130          * Note: This test assumes MAXNS == 3, which is the
131          * case on all systems encountered so far.
132          */
133         assert_int_equal(MAXNS, 3);
134         assert_int_equal(dnsstate.nscount, MAXNS);
135
136         /* Validate the servers. */
137
138         /* IPv4 */
139         assert_int_equal(dnsstate.nsaddr_list[0].sin_family, AF_INET);
140         assert_int_equal(dnsstate.nsaddr_list[0].sin_port, htons(53));
141         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[0].sin_addr),
142                   straddr, INET6_ADDRSTRLEN);
143         assert_string_equal(nameservers[0], straddr);
144 #ifdef HAVE_RESOLV_IPV6_NSADDRS
145         assert_null(dnsstate._u._ext.nsaddrs[0]);
146 #endif
147
148         assert_int_equal(dnsstate.nsaddr_list[1].sin_family, AF_INET);
149         assert_int_equal(dnsstate.nsaddr_list[1].sin_port, htons(53));
150         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[1].sin_addr),
151                   straddr, INET6_ADDRSTRLEN);
152         assert_string_equal(nameservers[1], straddr);
153 #ifdef HAVE_RESOLV_IPV6_NSADDRS
154         assert_null(dnsstate._u._ext.nsaddrs[1]);
155 #endif
156
157 #ifndef HAVE_RESOLV_IPV6_NSADDRS
158         /*
159          * On platforms that don't support IPv6, the v6 address is skipped
160          * and we end up reading three v4 addresses.
161          */
162         assert_int_equal(dnsstate.nsaddr_list[2].sin_family, AF_INET);
163         assert_int_equal(dnsstate.nsaddr_list[2].sin_port, htons(53));
164         inet_ntop(AF_INET, &(dnsstate.nsaddr_list[2].sin_addr),
165                   straddr, INET6_ADDRSTRLEN);
166         assert_string_equal(nameservers[3], straddr);
167 #else
168         /* IPv6 */
169         assert_non_null(dnsstate._u._ext.nsaddrs[2]);
170         sa6 = dnsstate._u._ext.nsaddrs[2];
171         assert_int_equal(sa6->sin6_family, AF_INET6);
172         assert_int_equal(sa6->sin6_port, htons(53));
173         inet_ntop(AF_INET6, &(sa6->sin6_addr), straddr, INET6_ADDRSTRLEN);
174         assert_string_equal(nameservers[2], straddr);
175 #endif
176
177         res_nclose(&dnsstate);
178 }
179
180 static void test_res_ninit_enoent(void **state)
181 {
182         int rv;
183         struct __res_state dnsstate;
184
185         (void) state; /* unused */
186
187         rv = setenv("RESOLV_WRAPPER_CONF", "/no/such/file", 1);
188         assert_int_equal(rv, 0);
189
190         /* Just make sure we don't crash, error is fine */
191         memset(&dnsstate, 0, sizeof(dnsstate));
192         rv = res_ninit(&dnsstate);
193         unsetenv("RESOLV_WRAPPER_CONF");
194         assert_int_equal(rv, -1);
195 }
196
197 int main(void) {
198         int rc;
199
200         const struct CMUnitTest init_tests[] = {
201                 cmocka_unit_test_setup_teardown(test_res_ninit, setup, teardown),
202                 cmocka_unit_test(test_res_ninit_enoent),
203         };
204
205         rc = cmocka_run_group_tests(init_tests, NULL, NULL);
206
207         return rc;
208 }