1 #include "config.h"
2 
3 #include <stdarg.h>
4 #include <stddef.h>
5 #include <setjmp.h>
6 #include <cmocka.h>
7 
8 #include <errno.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 #include <netdb.h>
18 
test_nwrap_getaddrinfo(void ** state)19 static void test_nwrap_getaddrinfo(void **state)
20 {
21 	struct addrinfo hints;
22 	struct addrinfo *res = NULL;
23 	struct sockaddr_in *sinp;
24 	struct sockaddr_in6 *sin6p;
25 	char ip6[INET6_ADDRSTRLEN];
26 	char *ip;
27 	int rc;
28 
29 	(void) state; /* unused */
30 
31 	/* IPv4 */
32 	memset(&hints, 0, sizeof(struct addrinfo));
33 	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
34 	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
35 	hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
36 	hints.ai_protocol = 0;          /* Any protocol */
37 	hints.ai_canonname = NULL;
38 	hints.ai_addr = NULL;
39 	hints.ai_next = NULL;
40 
41 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
42 	assert_int_equal(rc, 0);
43 	assert_non_null(res);
44 
45 	assert_non_null(res->ai_canonname);
46 	assert_string_equal(res->ai_canonname, "magrathea.galaxy.site");
47 
48 	assert_int_equal(res->ai_family, AF_INET);
49 
50 	sinp = (struct sockaddr_in *)res->ai_addr;
51 
52 	assert_int_equal(sinp->sin_family, AF_INET);
53 	ip = inet_ntoa(sinp->sin_addr);
54 
55 	assert_string_equal(ip, "127.0.0.11");
56 
57 	freeaddrinfo(res);
58 	res = NULL;
59 
60 	memset(&hints, 0, sizeof(struct addrinfo));
61 	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
62 	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
63 	hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
64 	hints.ai_protocol = 0;          /* Any protocol */
65 	hints.ai_canonname = NULL;
66 	hints.ai_addr = NULL;
67 	hints.ai_next = NULL;
68 
69 	rc = getaddrinfo("::13", NULL, &hints, &res);
70 	assert_non_null(res);
71 	assert_int_equal(rc, 0);
72 
73 	assert_non_null(res->ai_canonname);
74 	assert_string_equal(res->ai_canonname, "beteigeuze.galaxy.site");
75 
76 	assert_int_equal(res->ai_family, AF_INET6);
77 
78 	sin6p = (struct sockaddr_in6 *)res->ai_addr;
79 
80 	assert_int_equal(sin6p->sin6_family, AF_INET6);
81 	inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6));
82 
83 	assert_string_equal(ip6, "::13");
84 
85 	freeaddrinfo(res);
86 }
87 
88 /*
89  * The purpose of this test is to verify that reloading of the hosts
90  * file (triggered by a timestamp change) correctly frees and re-creates
91  * the internal data structures, so we do not end up using invalid memory.
92  */
test_nwrap_getaddrinfo_reload(void ** state)93 static void test_nwrap_getaddrinfo_reload(void **state)
94 {
95 	struct addrinfo hints;
96 	struct addrinfo *res = NULL;
97 	const char *env;
98 	char touch_cmd[1024];
99 	int rc;
100 
101 	(void) state; /* unused */
102 
103 	/* IPv4 */
104 	memset(&hints, 0, sizeof(struct addrinfo));
105 	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
106 	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
107 	hints.ai_flags = AI_PASSIVE;    /* For wildcard IP address */
108 	hints.ai_protocol = 0;          /* Any protocol */
109 	hints.ai_canonname = NULL;
110 	hints.ai_addr = NULL;
111 	hints.ai_next = NULL;
112 
113 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
114 	assert_int_equal(rc, 0);
115 	assert_non_null(res);
116 
117 	freeaddrinfo(res);
118 	res = NULL;
119 
120 	env = getenv("NSS_WRAPPER_HOSTS");
121 	assert_non_null(env);
122 
123 	snprintf(touch_cmd, sizeof(touch_cmd), "touch %s", env);
124 
125 	rc = system(touch_cmd);
126 	assert_return_code(rc, errno);
127 
128 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
129 	assert_int_equal(rc, 0);
130 	assert_non_null(res);
131 
132 
133 	freeaddrinfo(res);
134 }
135 
test_nwrap_getaddrinfo_samba(void ** state)136 static void test_nwrap_getaddrinfo_samba(void **state)
137 {
138 	struct addrinfo hints;
139 	struct addrinfo *res = NULL;
140 	int rc;
141 
142 	(void) state; /* unused */
143 
144 	/* IPv4 */
145 	memset(&hints, 0, sizeof(struct addrinfo));
146 	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
147 	hints.ai_socktype = SOCK_STREAM; /* Stream socket */
148 	hints.ai_flags = 0;    /* For wildcard IP address */
149 	hints.ai_protocol = IPPROTO_TCP;          /* Any protocol */
150 	hints.ai_canonname = NULL;
151 	hints.ai_addr = NULL;
152 	hints.ai_next = NULL;
153 
154 	rc = getaddrinfo("127.0.0.21", NULL, &hints, &res);
155 	assert_int_equal(rc, 0);
156 	assert_non_null(res);
157 	freeaddrinfo(res);
158 	res = NULL;
159 
160 	rc = getaddrinfo("samba.example.com", NULL, &hints, &res);
161 	assert_int_equal(rc, 0);
162 	assert_non_null(res);
163 	freeaddrinfo(res);
164 	res = NULL;
165 
166 	rc = getaddrinfo("localdc", NULL, &hints, &res);
167 	assert_int_equal(rc, 0);
168 	assert_non_null(res);
169 	freeaddrinfo(res);
170 	res = NULL;
171 
172 	rc = getaddrinfo("localdc.samba.example.com", NULL, &hints, &res);
173 	assert_int_equal(rc, 0);
174 	assert_non_null(res);
175 	freeaddrinfo(res);
176 	res = NULL;
177 
178 	rc = getaddrinfo("fd00:0000:0000:0000:0000:0000:5357:5f15", NULL, &hints, &res);
179 	assert_int_equal(rc, 0);
180 	assert_non_null(res);
181 
182 	freeaddrinfo(res);
183 }
184 
test_nwrap_getaddrinfo_any(void ** state)185 static void test_nwrap_getaddrinfo_any(void **state)
186 {
187 	struct addrinfo hints;
188 	struct addrinfo *res = NULL;
189 	struct sockaddr_in *sinp;
190 	struct sockaddr_in6 *sin6p;
191 	char ip6[INET6_ADDRSTRLEN];
192 	char *ip;
193 	int rc;
194 
195 	(void) state; /* unused */
196 
197 	/* IPv4 */
198 	memset(&hints, 0, sizeof(struct addrinfo));
199 	hints.ai_family = AF_INET;
200 	hints.ai_socktype = SOCK_STREAM;
201 	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
202 
203 	rc = getaddrinfo("0.0.0.0", "389", &hints, &res);
204 	assert_int_equal(rc, 0);
205 	assert_non_null(res);
206 
207 	assert_int_equal(res->ai_family, AF_INET);
208 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
209 
210 	assert_null(res->ai_canonname);
211 
212 	sinp = (struct sockaddr_in *)res->ai_addr;
213 
214 	assert_int_equal(389, htons(sinp->sin_port));
215 
216 	ip = inet_ntoa(sinp->sin_addr);
217 
218 	assert_string_equal(ip, "0.0.0.0");
219 
220 	freeaddrinfo(res);
221 	res = NULL;
222 
223 	/* IPv4 */
224 	memset(&hints, 0, sizeof(struct addrinfo));
225 	hints.ai_family = AF_INET6;
226 	hints.ai_socktype = SOCK_STREAM;
227 	hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
228 
229 	rc = getaddrinfo("::", "389", &hints, &res);
230 	assert_int_equal(rc, 0);
231 	assert_non_null(res);
232 
233 	assert_int_equal(res->ai_family, AF_INET6);
234 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
235 
236 	assert_null(res->ai_canonname);
237 
238 	sin6p = (struct sockaddr_in6 *)res->ai_addr;
239 
240 	assert_int_equal(389, htons(sin6p->sin6_port));
241 
242 	inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6));
243 
244 	assert_string_equal(ip6, "::");
245 
246 	freeaddrinfo(res);
247 }
248 
test_nwrap_getaddrinfo_local(void ** state)249 static void test_nwrap_getaddrinfo_local(void **state)
250 {
251 	struct addrinfo hints;
252 	struct addrinfo *res;
253 	struct sockaddr_in *sinp;
254 	char *ip;
255 	int rc;
256 
257 	(void) state; /* unused */
258 
259 	/* IPv4 */
260 	memset(&hints, 0, sizeof(struct addrinfo));
261 	hints.ai_family = AF_UNSPEC;
262 	hints.ai_socktype = SOCK_STREAM;
263 	hints.ai_flags = 0;
264 
265 	rc = getaddrinfo("127.0.0.1", NULL, &hints, &res);
266 	assert_int_equal(rc, 0);
267 
268 	assert_int_equal(res->ai_family, AF_INET);
269 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
270 
271 	assert_null(res->ai_canonname);
272 
273 	sinp = (struct sockaddr_in *)res->ai_addr;
274 	ip = inet_ntoa(sinp->sin_addr);
275 
276 	assert_string_equal(ip, "127.0.0.1");
277 
278 	freeaddrinfo(res);
279 }
280 
test_nwrap_getaddrinfo_name(void ** state)281 static void test_nwrap_getaddrinfo_name(void **state)
282 {
283 	struct addrinfo hints;
284 	struct addrinfo *res = NULL;
285 	struct sockaddr_in *sinp;
286 	char *ip;
287 	int rc;
288 
289 	(void) state; /* unused */
290 
291 	/* IPv4 */
292 	memset(&hints, 0, sizeof(struct addrinfo));
293 	hints.ai_family = AF_UNSPEC;
294 	hints.ai_socktype = SOCK_STREAM;
295 	hints.ai_flags = 0;
296 
297 	rc = getaddrinfo("maximegalon.galaxy.site", NULL, &hints, &res);
298 	assert_int_equal(rc, 0);
299 	assert_non_null(res);
300 
301 	assert_non_null(res);
302 	assert_int_equal(res->ai_family, AF_INET);
303 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
304 
305 	assert_non_null(res->ai_canonname);
306 	assert_string_equal(res->ai_canonname, "maximegalon.galaxy.site");
307 
308 	sinp = (struct sockaddr_in *)res->ai_addr;
309 	ip = inet_ntoa(sinp->sin_addr);
310 
311 	assert_string_equal(ip, "127.0.0.12");
312 
313 	freeaddrinfo(res);
314 	res = NULL;
315 
316 	/* IPv4 */
317 	memset(&hints, 0, sizeof(struct addrinfo));
318 	hints.ai_family = AF_UNSPEC;
319 	hints.ai_socktype = SOCK_STREAM;
320 	hints.ai_flags = 0;
321 
322 	rc = getaddrinfo("MAGRATHEA", NULL, &hints, &res);
323 	assert_int_equal(rc, 0);
324 
325 	assert_non_null(res);
326 	assert_int_equal(res->ai_family, AF_INET);
327 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
328 
329 	assert_non_null(res->ai_canonname);
330 	assert_string_equal(res->ai_canonname, "magrathea.galaxy.site");
331 
332 	sinp = (struct sockaddr_in *)res->ai_addr;
333 	ip = inet_ntoa(sinp->sin_addr);
334 
335 	assert_string_equal(ip, "127.0.0.11");
336 
337 	freeaddrinfo(res);
338 }
339 
test_nwrap_getaddrinfo_service(void ** state)340 static void test_nwrap_getaddrinfo_service(void **state)
341 {
342 	struct addrinfo hints;
343 	struct addrinfo *res = NULL;
344 	struct sockaddr_in *sinp;
345 	char *ip;
346 	int rc;
347 
348 	(void) state; /* unused */
349 
350 	/* IPv4 */
351 	memset(&hints, 0, sizeof(struct addrinfo));
352 	hints.ai_family = AF_UNSPEC;
353 	hints.ai_socktype = SOCK_STREAM;
354 	hints.ai_flags = 0;
355 
356 	rc = getaddrinfo("magrathea", "wurst", &hints, &res);
357 	assert_int_equal(rc, EAI_NONAME);
358 
359 	/* Check ldap port */
360 	rc = getaddrinfo("magrathea", "ldap", &hints, &res);
361 	assert_int_equal(rc, 0);
362 	assert_non_null(res);
363 
364 	assert_int_equal(res->ai_family, AF_INET);
365 	assert_int_equal(res->ai_socktype, SOCK_STREAM);
366 
367 	assert_non_null(res->ai_canonname);
368 	assert_string_equal(res->ai_canonname, "magrathea.galaxy.site");
369 
370 	assert_non_null(res->ai_addr);
371 	sinp = (struct sockaddr_in *)res->ai_addr;
372 	ip = inet_ntoa(sinp->sin_addr);
373 
374 	assert_string_equal(ip, "127.0.0.11");
375 
376 	assert_int_equal(ntohs(sinp->sin_port), 389);
377 
378 	freeaddrinfo(res);
379 }
380 
test_nwrap_getaddrinfo_null(void ** state)381 static void test_nwrap_getaddrinfo_null(void **state)
382 {
383 	struct addrinfo hints;
384 	struct addrinfo *res = NULL;
385 	struct sockaddr_in6 *sin6p;
386 	char ip6[INET6_ADDRSTRLEN];
387 	int rc;
388 
389 	(void) state; /* unused */
390 
391 	memset(&hints, 0, sizeof(struct addrinfo));
392 	hints.ai_family = AF_INET6;
393 	hints.ai_socktype = SOCK_DGRAM;
394 	hints.ai_protocol = 17;
395 	hints.ai_flags = 0;
396 
397 	rc = getaddrinfo(NULL, NULL, &hints, &res);
398 	assert_int_equal(rc, EAI_NONAME);
399 
400 	/* Check dns service */
401 	rc = getaddrinfo(NULL, "domain", &hints, &res);
402 	assert_int_equal(rc, 0);
403 
404 	assert_non_null(res);
405 	assert_null(res->ai_canonname);
406 
407 	assert_int_equal(res->ai_family, AF_INET6);
408 	assert_int_equal(res->ai_socktype, SOCK_DGRAM);
409 
410 	assert_non_null(res->ai_addr);
411 	sin6p = (struct sockaddr_in6 *)res->ai_addr;
412 	inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6));
413 
414 	assert_string_equal(ip6, "::1");
415 
416 	freeaddrinfo(res);
417 	res = NULL;
418 
419 	/* Check dns service */
420 	rc = getaddrinfo("magrathea", "domain", NULL, &res);
421 	assert_non_null(res);
422 	assert_int_equal(rc, 0);
423 
424 	assert_non_null(res->ai_canonname);
425 
426 	freeaddrinfo(res);
427 }
428 
test_nwrap_getaddrinfo_dot(void ** state)429 static void test_nwrap_getaddrinfo_dot(void **state)
430 {
431 	struct addrinfo hints = {
432 		.ai_family = AF_INET,
433 	};
434 	struct addrinfo *res = NULL;
435 	struct sockaddr_in *sinp;
436 	char ip[INET_ADDRSTRLEN];
437 	int rc;
438 
439 	(void) state; /* unused */
440 
441 	/* Check with a dot at the end */
442 	rc = getaddrinfo("magrathea.galaxy.site.", NULL, &hints, &res);
443 	assert_int_equal(rc, 0);
444 	assert_non_null(res);
445 
446 	assert_non_null(res->ai_next);
447 	assert_int_equal(res->ai_family, AF_INET);
448 
449 	sinp = (struct sockaddr_in *)res->ai_addr;
450 	assert_int_equal(sinp->sin_family, AF_INET);
451 	inet_ntop(AF_INET, (void *)&sinp->sin_addr, ip, sizeof(ip));
452 
453 	assert_string_equal(ip, "127.0.0.11");
454 
455 	freeaddrinfo(res);
456 }
457 
test_nwrap_getaddrinfo_ipv6(void ** state)458 static void test_nwrap_getaddrinfo_ipv6(void **state)
459 {
460 	struct addrinfo hints;
461 	struct addrinfo *res = NULL;
462 	struct sockaddr_in6 *sin6p;
463 	char ip6[INET6_ADDRSTRLEN];
464 	int rc;
465 
466 	(void) state; /* unused */
467 
468 	/*
469 	 * krikkit.galaxy has an IPv4 and IPv6 address, this should only
470 	 * return the IPv6 address.
471 	 */
472 	memset(&hints, 0, sizeof(struct addrinfo));
473 	hints.ai_family = AF_INET6;
474 
475 	rc = getaddrinfo("krikkit.galaxy.site", NULL, &hints, &res);
476 	assert_int_equal(rc, 0);
477 	assert_non_null(res);
478 
479 	assert_non_null(res->ai_next);
480 	assert_int_equal(res->ai_family, AF_INET6);
481 
482 	sin6p = (struct sockaddr_in6 *)res->ai_addr;
483 	assert_int_equal(sin6p->sin6_family, AF_INET6);
484 	inet_ntop(AF_INET6, (void *)&sin6p->sin6_addr, ip6, sizeof(ip6));
485 
486 	assert_string_equal(ip6, "::14");
487 
488 	freeaddrinfo(res);
489 }
490 
test_nwrap_getaddrinfo_multiple_mixed(void ** state)491 static void test_nwrap_getaddrinfo_multiple_mixed(void **state)
492 {
493 	struct addrinfo *res, *res_head;
494 	struct addrinfo hints;
495 	unsigned int ipv6_count = 0;
496 	unsigned int ipv4_count = 0;
497 	int rc;
498 	int p;
499 
500 	struct sockaddr_in *r_addr;
501 	struct sockaddr_in6 *r_addr6;
502 
503 	const char *result = NULL;
504 	const char *value = NULL;
505 
506 	/* For inet_ntop call */
507 	char buf[4096];
508 
509 	/* 2 - ipv4 and 3 ipv6 addresses */
510 	const char *ipvX_results[] = {"127.1.1.1", "127.0.0.66", "2666::22", "B00B:5::4", "DEAD:BEEF:1:2:3::4", NULL};
511 
512 	(void) state; /* unused */
513 
514 	 memset(&hints, '\0', sizeof(struct addrinfo));
515         hints.ai_protocol = IPPROTO_TCP;
516         hints.ai_family = AF_UNSPEC;
517         hints.ai_socktype = SOCK_STREAM;
518 
519 	rc = getaddrinfo("pumpkin.bunny.net", NULL, &hints, &res_head);
520 	assert_return_code(rc, 0);
521 	assert_non_null(res_head);
522 
523 	for (res = res_head; res != NULL; res = res->ai_next) {
524 		if (res->ai_family == AF_INET) {
525 			r_addr = (struct sockaddr_in *) res->ai_addr;
526 			assert_non_null(r_addr);
527 			++ipv4_count;
528 			result = inet_ntop(AF_INET,
529 					   &r_addr->sin_addr,
530 					   buf,
531 					   4096);
532 		} else if (res->ai_family == AF_INET6) {
533 			r_addr6 = (struct sockaddr_in6 *) res->ai_addr;
534 			assert_non_null(r_addr6);
535 			++ipv6_count;
536 			result = inet_ntop(AF_INET6,
537 					   &r_addr6->sin6_addr,
538 					   buf,
539 					   4096);
540 		} else {
541 			/* Unknown family type */
542 			assert_int_equal(1,0);
543 		}
544 
545 		/* Important part */
546 		assert_non_null(result);
547 
548 		/* This could be part of cmocka library */
549 		for (value = ipvX_results[0], p = 0; value != NULL; value = ipvX_results[++p]) {
550 			if (strcasecmp(value, result) == 0) {
551 				break;
552 			}
553 		}
554 		assert_non_null(value);
555 	}
556 
557 	assert_int_equal(ipv6_count, 3);
558 	assert_int_equal(ipv4_count, 2);
559 
560 	freeaddrinfo(res_head);
561 }
562 
test_nwrap_getaddrinfo_flags_ai_numericserv(void ** state)563 static void test_nwrap_getaddrinfo_flags_ai_numericserv(void **state)
564 {
565 	struct addrinfo hints;
566 	struct addrinfo *res;
567 	int rc;
568 
569 	(void) state; /* unused */
570 
571 	memset(&hints, 0, sizeof(struct addrinfo));
572 	hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
573 	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
574 	hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;    /* For wildcard IP address */
575 	hints.ai_protocol = 0;          /* Any protocol */
576 	hints.ai_canonname = NULL;
577 
578 	/*
579 	 * Calls with NULL name are handled by libc,
580 	 * even if nss_wrapper is enabled
581 	 */
582 
583 	rc = getaddrinfo(NULL, "echo", &hints, &res);
584 	assert_int_equal(rc, EAI_NONAME);
585 
586 	rc = getaddrinfo(NULL, "80", &hints, &res);
587 	assert_int_equal(rc, 0);
588 	freeaddrinfo(res);
589 	res = NULL;
590 
591 	/* Crippled input */
592 	rc = getaddrinfo(NULL, "80a1", &hints, &res);
593 	assert_int_equal(rc, EAI_NONAME);
594 
595 	/*
596 	 * Calls with non-NULL name are handled by nwrap
597 	 */
598 
599 	rc = getaddrinfo("magrathea.galaxy.site", "echo", &hints, &res);
600 	assert_int_equal(rc, EAI_NONAME);
601 
602 	rc = getaddrinfo("magrathea.galaxy.site", "80", &hints, &res);
603 	assert_int_equal(rc, 0);
604 	freeaddrinfo(res);
605 	res = NULL;
606 
607 	/* Crippled input */
608 	rc = getaddrinfo("magrathea.galaxy.site", "80a1", &hints, &res);
609 	assert_int_equal(rc, EAI_NONAME);
610 }
611 
test_nwrap_getaddrinfo_flags_ai_numerichost(void ** state)612 static void test_nwrap_getaddrinfo_flags_ai_numerichost(void **state)
613 {
614 	struct addrinfo hints;
615 	struct addrinfo *res;
616 	int rc;
617 
618 	(void) state; /* unused */
619 
620 	memset(&hints, 0, sizeof(struct addrinfo));
621 	hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
622 	hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;  /* For wildcard IP address */
623 	hints.ai_protocol = 0;          /* Any protocol */
624 	hints.ai_canonname = NULL;
625 
626 	/* IPv4 or IPv6 */
627 
628 	hints.ai_family = AF_UNSPEC;
629 
630 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
631 	assert_int_equal(rc, 0);
632 	freeaddrinfo(res);
633 
634 	rc = getaddrinfo("::1", NULL, &hints, &res);
635 	assert_int_equal(rc, 0);
636 	freeaddrinfo(res);
637 
638 	rc = getaddrinfo(NULL, "echo", &hints, &res);
639 	assert_int_equal(rc, 0);
640 	freeaddrinfo(res);
641 
642 	rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res);
643 	assert_int_equal(rc, EAI_NONAME);
644 
645 	rc = getaddrinfo("", NULL, &hints, &res);
646 	assert_int_equal(rc, EAI_NONAME);
647 
648 	rc = getaddrinfo("fail.me", "echo", &hints, &res);
649 	assert_int_equal(rc, EAI_NONAME);
650 
651 	/* IPv4 */
652 
653 	hints.ai_family = AF_INET;
654 
655 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
656 	assert_int_equal(rc, 0);
657 	freeaddrinfo(res);
658 
659 	rc = getaddrinfo("::1", NULL, &hints, &res);
660 #ifdef EAI_ADDRFAMILY
661 	assert_int_equal(rc, EAI_ADDRFAMILY);
662 #else
663 	assert_int_equal(rc, EAI_FAMILY);
664 #endif
665 
666 	rc = getaddrinfo(NULL, "echo", &hints, &res);
667 	assert_int_equal(rc, 0);
668 	freeaddrinfo(res);
669 
670 	rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res);
671 	assert_int_equal(rc, EAI_NONAME);
672 
673 	rc = getaddrinfo("", NULL, &hints, &res);
674 	assert_int_equal(rc, EAI_NONAME);
675 
676 	rc = getaddrinfo("fail.me", "echo", &hints, &res);
677 	assert_int_equal(rc, EAI_NONAME);
678 
679 
680 	/* IPv6 */
681 
682 	hints.ai_family = AF_INET6;
683 
684 	rc = getaddrinfo("127.0.0.11", NULL, &hints, &res);
685 #ifdef EAI_ADDRFAMILY
686 	assert_int_equal(rc, EAI_ADDRFAMILY);
687 #else
688 	assert_int_equal(rc, EAI_FAMILY);
689 #endif
690 
691 	rc = getaddrinfo("::1", NULL, &hints, &res);
692 	assert_int_equal(rc, 0);
693 	freeaddrinfo(res);
694 
695 	rc = getaddrinfo(NULL, "echo", &hints, &res);
696 	assert_int_equal(rc, 0);
697 	freeaddrinfo(res);
698 
699 	rc = getaddrinfo("magrathea.galaxy.site", NULL, &hints, &res);
700 	assert_int_equal(rc, EAI_NONAME);
701 
702 	rc = getaddrinfo("", NULL, &hints, &res);
703 	assert_int_equal(rc, EAI_NONAME);
704 
705 	rc = getaddrinfo("fail.me", "echo", &hints, &res);
706 	assert_int_equal(rc, EAI_NONAME);
707 }
708 
main(void)709 int main(void) {
710 	int rc;
711 
712 	const struct CMUnitTest tests[] = {
713 		cmocka_unit_test(test_nwrap_getaddrinfo),
714 		cmocka_unit_test(test_nwrap_getaddrinfo_reload),
715 		cmocka_unit_test(test_nwrap_getaddrinfo_any),
716 		cmocka_unit_test(test_nwrap_getaddrinfo_local),
717 		cmocka_unit_test(test_nwrap_getaddrinfo_name),
718 		cmocka_unit_test(test_nwrap_getaddrinfo_service),
719 		cmocka_unit_test(test_nwrap_getaddrinfo_null),
720 		cmocka_unit_test(test_nwrap_getaddrinfo_dot),
721 		cmocka_unit_test(test_nwrap_getaddrinfo_ipv6),
722 		cmocka_unit_test(test_nwrap_getaddrinfo_multiple_mixed),
723 		cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numericserv),
724 		cmocka_unit_test(test_nwrap_getaddrinfo_flags_ai_numerichost),
725 		cmocka_unit_test(test_nwrap_getaddrinfo_samba),
726 	};
727 
728 	rc = cmocka_run_group_tests(tests, NULL, NULL);
729 
730 	return rc;
731 }
732