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