1 #include "config.h"
2
3 #include <pthread.h>
4
5 #include <stdarg.h>
6 #include <stddef.h>
7 #include <setjmp.h>
8 #include <cmocka.h>
9
10 #include <errno.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20
21 #define NSS_WRAPPER_HOSTNAME_ENV "NSS_WRAPPER_HOSTNAME"
22
test_nwrap_gethostname(void ** state)23 static void test_nwrap_gethostname(void **state)
24 {
25 const char *hostname = "milliways";
26 char sys_host[256] = {0};
27 char host[16] = {0};
28 int rc;
29
30 (void) state; /* unused */
31
32 rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, hostname, 1);
33 assert_int_equal(rc, 0);
34
35 rc = gethostname(host, sizeof(host));
36 assert_int_equal(rc, 0);
37
38 assert_string_equal(host, hostname);
39
40 rc = setenv(NSS_WRAPPER_HOSTNAME_ENV, "this_hostname_is_too_long", 1);
41 assert_int_equal(rc, 0);
42
43 rc = gethostname(host, sizeof(host));
44 assert_int_equal(rc, -1);
45 assert_int_equal(errno, ENAMETOOLONG);
46
47 unsetenv(NSS_WRAPPER_HOSTNAME_ENV);
48
49 rc = gethostname(sys_host, sizeof(sys_host));
50 assert_int_equal(rc, 0);
51
52 }
53
thread_test_gethostbyname(void * u)54 static void *thread_test_gethostbyname(void *u)
55 {
56 struct hostent *he;
57
58 (void) u; /* unused */
59
60 he = gethostbyname("magrathea");
61 assert_non_null(he);
62 assert_non_null(he->h_name);
63 assert_string_equal(he->h_name, "magrathea.galaxy.site");
64 pthread_exit(NULL);
65 }
66
test_nwrap_gethostbyname_thread(void ** state)67 static void test_nwrap_gethostbyname_thread(void **state)
68 {
69 struct hostent *he;
70 pthread_t th;
71
72 (void) state; /* unused */
73
74 he = gethostbyname("maximegalon.galaxy.site");
75 assert_non_null(he);
76 assert_non_null(he->h_name);
77 assert_string_equal(he->h_name, "maximegalon.galaxy.site");
78
79 pthread_create(&th, NULL, &thread_test_gethostbyname, NULL);
80 pthread_join(th, NULL);
81
82 assert_non_null(he);
83 assert_non_null(he->h_name);
84 #ifdef BSD
85 /*
86 * On *BSD (and Mac OS X) systems,
87 * data is stored in thread local storage.
88 */
89 assert_string_equal(he->h_name, "maximegalon.galaxy.site");
90 #else
91 /*
92 * Glibc doesn't store data in thread local storage, so calling
93 * gethostbyname from a thread overwrites the parent thread's data.
94 */
95 assert_string_equal(he->h_name, "magrathea.galaxy.site");
96 #endif
97 }
98
test_nwrap_gethostbyname(void ** state)99 static void test_nwrap_gethostbyname(void **state)
100 {
101 char ip[INET_ADDRSTRLEN];
102 struct hostent *he;
103 const char *a;
104
105 (void) state; /* unused */
106
107 he = gethostbyname("magrathea.galaxy.site");
108 assert_non_null(he);
109 assert_non_null(he->h_name);
110 assert_non_null(he->h_addr_list);
111
112 assert_string_equal(he->h_name, "magrathea.galaxy.site");
113 assert_int_equal(he->h_addrtype, AF_INET);
114
115 a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
116 assert_non_null(a);
117
118 assert_string_equal(ip, "127.0.0.11");
119 }
120
test_nwrap_gethostbyname_multiple(void ** state)121 static void test_nwrap_gethostbyname_multiple(void **state)
122 {
123 struct hostent *he;
124 char **list;
125
126 /* For inet_ntop call */
127 char buf[4096];
128 const char *result;
129 char *p = buf;
130
131 /* List of ips in hosts file - order matters */
132 const char *const result_ips[] = { "127.0.0.11", "127.0.0.12", NULL };
133 const char *actual_ip = result_ips[0];
134 unsigned int ac;
135
136 (void) state; /* unused */
137
138 he = gethostbyname("magrathea.galaxy.site");
139 assert_non_null(he);
140 assert_non_null(he->h_name);
141 assert_non_null(he->h_addr_list);
142
143 list = he->h_addr_list;
144 for (ac = 0; *list != NULL; ++ac, ++list) {
145 actual_ip = result_ips[ac];
146 /* When test fails here more records are returned */
147 assert_non_null(actual_ip);
148 result = inet_ntop(AF_INET, *list, p, 4096);
149 assert_non_null(p);
150 assert_string_equal(actual_ip, result);
151 }
152 }
153
154 #ifdef HAVE_GETHOSTBYNAME2
test_nwrap_gethostbyname2(void ** state)155 static void test_nwrap_gethostbyname2(void **state)
156 {
157 char ip[INET6_ADDRSTRLEN];
158 struct hostent *he;
159 const char *a;
160
161 (void) state; /* unused */
162
163 he = gethostbyname2("magrathea.galaxy.site", AF_INET6);
164 assert_non_null(he);
165
166 he = gethostbyname2("magrathea.galaxy.site", AF_INET);
167 assert_non_null(he);
168
169 /* Check ipv6 he */
170 he = gethostbyname2("krikkit.galaxy.site", AF_INET6);
171 assert_non_null(he);
172 assert_non_null(he->h_name);
173 assert_non_null(he->h_addr_list);
174
175 assert_string_equal(he->h_name, "krikkit.galaxy.site");
176 assert_int_equal(he->h_addrtype, AF_INET6);
177
178 a = inet_ntop(AF_INET6, he->h_addr_list[0], ip, sizeof(ip));
179 assert_non_null(a);
180
181 assert_string_equal(ip, "::14");
182
183 /* Check ipv4 he */
184 he = gethostbyname2("krikkit.galaxy.site", AF_INET);
185 assert_non_null(he);
186 assert_non_null(he->h_name);
187 assert_non_null(he->h_addr_list);
188
189 assert_string_equal(he->h_name, "krikkit.galaxy.site");
190 assert_int_equal(he->h_addrtype, AF_INET);
191
192 a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
193 assert_non_null(a);
194
195 assert_string_equal(ip, "127.0.0.14");
196 }
197 #endif /* HAVE_GETHOSTBYNAME2 */
198
test_nwrap_gethostbyaddr(void ** state)199 static void test_nwrap_gethostbyaddr(void **state)
200 {
201 struct hostent *he;
202 struct in_addr in;
203 int rc;
204
205 (void) state; /* unused */
206
207 rc = inet_aton("127.0.0.11", &in);
208 assert_int_equal(rc, 1);
209
210 he = gethostbyaddr(&in, sizeof(struct in_addr), AF_INET);
211 assert_non_null(he);
212 assert_non_null(he->h_name);
213 assert_non_null(he->h_addr_list);
214
215 assert_string_equal(he->h_name, "magrathea.galaxy.site");
216 assert_int_equal(he->h_addrtype, AF_INET);
217 assert_memory_equal(&in, he->h_addr_list[0], he->h_length);
218 }
219
220 #ifdef HAVE_GETHOSTBYNAME_R
test_nwrap_gethostbyname_r(void ** state)221 static void test_nwrap_gethostbyname_r(void **state)
222 {
223 char buf[1024] = {0};
224 char ip[INET_ADDRSTRLEN];
225 struct hostent hb, *he;
226 const char *a;
227 int herr = 0;
228 int rc;
229
230 (void) state; /* unused */
231
232 rc = gethostbyname_r("magrathea.galaxy.site",
233 &hb,
234 buf, sizeof(buf),
235 &he,
236 &herr);
237 assert_int_equal(rc, 0);
238 assert_non_null(he);
239 assert_non_null(he->h_name);
240 assert_non_null(he->h_addr_list);
241
242 assert_string_equal(he->h_name, "magrathea.galaxy.site");
243 assert_int_equal(he->h_addrtype, AF_INET);
244
245 a = inet_ntop(AF_INET, he->h_addr_list[0], ip, sizeof(ip));
246 assert_non_null(a);
247
248 assert_string_equal(ip, "127.0.0.11");
249 }
250 #endif
251
252 #ifdef HAVE_GETHOSTBYADDR_R
test_nwrap_gethostbyaddr_r(void ** state)253 static void test_nwrap_gethostbyaddr_r(void **state)
254 {
255 char buf[1024] = {0};
256 struct hostent hb, *he;
257 struct in_addr in;
258 int herr = 0;
259 int rc;
260
261 (void) state; /* unused */
262
263 rc = inet_aton("127.0.0.11", &in);
264 assert_int_equal(rc, 1);
265
266 rc = gethostbyaddr_r(&in, sizeof(struct in_addr),
267 AF_INET,
268 &hb,
269 buf, sizeof(buf),
270 &he,
271 &herr);
272 assert_int_equal(rc, 0);
273 assert_non_null(he);
274 assert_non_null(he->h_name);
275 assert_non_null(he->h_addr_list);
276
277 assert_string_equal(he->h_name, "magrathea.galaxy.site");
278 assert_int_equal(he->h_addrtype, AF_INET);
279 assert_memory_equal(&in, he->h_addr_list[0], he->h_length);
280 }
281 #endif
282
main(void)283 int main(void) {
284 int rc;
285
286 const struct CMUnitTest tests[] = {
287 cmocka_unit_test(test_nwrap_gethostname),
288 cmocka_unit_test(test_nwrap_gethostbyname),
289 cmocka_unit_test(test_nwrap_gethostbyname_thread),
290 #ifdef HAVE_GETHOSTBYNAME2
291 cmocka_unit_test(test_nwrap_gethostbyname2),
292 #endif
293 cmocka_unit_test(test_nwrap_gethostbyaddr),
294 #ifdef HAVE_GETHOSTBYNAME_R
295 cmocka_unit_test(test_nwrap_gethostbyname_r),
296 #endif
297 #ifdef HAVE_GETHOSTBYADDR_R
298 cmocka_unit_test(test_nwrap_gethostbyaddr_r),
299 #endif
300 cmocka_unit_test(test_nwrap_gethostbyname_multiple),
301 };
302
303 rc = cmocka_run_group_tests(tests, NULL, NULL);
304
305 return rc;
306 }
307
308