xref: /minix3/minix/tests/test48.c (revision ad920fc485da86e45a88f73a98077b92da1288a3)
1433d6423SLionel Sambuc #include <arpa/inet.h>
2433d6423SLionel Sambuc #include <assert.h>
3433d6423SLionel Sambuc #include <netdb.h>
4433d6423SLionel Sambuc #include <stdio.h>
5433d6423SLionel Sambuc #include <stdlib.h>
6433d6423SLionel Sambuc #include <string.h>
7433d6423SLionel Sambuc #include <unistd.h>
8433d6423SLionel Sambuc 
9433d6423SLionel Sambuc int max_error = 3;
10433d6423SLionel Sambuc #include "common.h"
11433d6423SLionel Sambuc 
12433d6423SLionel Sambuc #define err() e(__LINE__)
13433d6423SLionel Sambuc 
printstr(const char * s)14433d6423SLionel Sambuc static void printstr(const char *s)
15433d6423SLionel Sambuc {
16433d6423SLionel Sambuc 	if (s)
17433d6423SLionel Sambuc 		printf("\"%s\"", s);
18433d6423SLionel Sambuc 	else
19433d6423SLionel Sambuc 		printf("NULL");
20433d6423SLionel Sambuc }
21433d6423SLionel Sambuc 
test_getaddrinfo_err(int n,const char * nodename,const char * servname,int passhints,int flags,int family,int socktype,const char * exp_result,const char * result)22433d6423SLionel Sambuc static void test_getaddrinfo_err(
23433d6423SLionel Sambuc 	int n,
24433d6423SLionel Sambuc 	const char *nodename,
25433d6423SLionel Sambuc 	const char *servname,
26433d6423SLionel Sambuc 	int passhints,
27433d6423SLionel Sambuc 	int flags,
28433d6423SLionel Sambuc 	int family,
29433d6423SLionel Sambuc 	int socktype,
30433d6423SLionel Sambuc 	const char *exp_result,
31433d6423SLionel Sambuc 	const char *result)
32433d6423SLionel Sambuc {
33433d6423SLionel Sambuc 	printf("error %d: getaddrinfo(", n);
34433d6423SLionel Sambuc 	printstr(nodename);
35433d6423SLionel Sambuc 	printf(", ");
36433d6423SLionel Sambuc 	printstr(servname);
37433d6423SLionel Sambuc 	printf(", ");
38433d6423SLionel Sambuc 	if (passhints)
39433d6423SLionel Sambuc 		printf("{ 0x%x, %d, %d }", flags, family, socktype);
40433d6423SLionel Sambuc 	else
41433d6423SLionel Sambuc 		printf("NULL");
42433d6423SLionel Sambuc 
43433d6423SLionel Sambuc 	printf("); result: ");
44433d6423SLionel Sambuc 	printstr(result);
45433d6423SLionel Sambuc 	printf("; expected: ");
46433d6423SLionel Sambuc 	printstr(exp_result);
47433d6423SLionel Sambuc 	printf("\n");
48433d6423SLionel Sambuc 	err();
49433d6423SLionel Sambuc }
50433d6423SLionel Sambuc 
51433d6423SLionel Sambuc /* yes, this is ugly, but not as ugly as repeating it all every time */
52433d6423SLionel Sambuc #define TEST_GETADDRINFO_ERR_PARAMS \
53433d6423SLionel Sambuc 	nodename, servname, passhints, flags, family, socktype
54433d6423SLionel Sambuc 
test_getaddrinfo_err_nr(int n,const char * nodename,const char * servname,int passhints,int flags,int family,int socktype,int exp_result,int result)55433d6423SLionel Sambuc static void test_getaddrinfo_err_nr(
56433d6423SLionel Sambuc 	int n,
57433d6423SLionel Sambuc 	const char *nodename,
58433d6423SLionel Sambuc 	const char *servname,
59433d6423SLionel Sambuc 	int passhints,
60433d6423SLionel Sambuc 	int flags,
61433d6423SLionel Sambuc 	int family,
62433d6423SLionel Sambuc 	int socktype,
63433d6423SLionel Sambuc 	int exp_result,
64433d6423SLionel Sambuc 	int result)
65433d6423SLionel Sambuc {
66433d6423SLionel Sambuc 	char exp_result_s[23], result_s[23];
67433d6423SLionel Sambuc 
68433d6423SLionel Sambuc 	/* convert result to string */
69433d6423SLionel Sambuc 	snprintf(exp_result_s, sizeof(exp_result_s), "%d/0x%x",
70433d6423SLionel Sambuc 		exp_result, exp_result);
71433d6423SLionel Sambuc 	snprintf(result_s, sizeof(result_s), "%d/0x%x", result, result);
72433d6423SLionel Sambuc 	test_getaddrinfo_err(n, TEST_GETADDRINFO_ERR_PARAMS,
73433d6423SLionel Sambuc 		exp_result_s, result_s);
74433d6423SLionel Sambuc }
75433d6423SLionel Sambuc 
test_getnameinfo_err(int n,unsigned long ipaddr,unsigned short port,socklen_t nodelen,socklen_t servicelen,int flags,const char * exp_result,const char * result)76433d6423SLionel Sambuc static void test_getnameinfo_err(
77433d6423SLionel Sambuc 	int n,
78433d6423SLionel Sambuc 	unsigned long ipaddr,
79433d6423SLionel Sambuc 	unsigned short port,
80433d6423SLionel Sambuc 	socklen_t nodelen,
81433d6423SLionel Sambuc 	socklen_t servicelen,
82433d6423SLionel Sambuc 	int flags,
83433d6423SLionel Sambuc 	const char *exp_result,
84433d6423SLionel Sambuc 	const char *result)
85433d6423SLionel Sambuc {
86433d6423SLionel Sambuc 	printf("error %d: getnameinfo(0x%.8x, %d, %d, %d, 0x%x); result: ",
87433d6423SLionel Sambuc 		n, ntohl(ipaddr), ntohs(port), nodelen, servicelen, flags);
88433d6423SLionel Sambuc 	printstr(result);
89433d6423SLionel Sambuc 	printf("; expected: ");
90433d6423SLionel Sambuc 	printstr(exp_result);
91433d6423SLionel Sambuc 	printf("\n");
92433d6423SLionel Sambuc 	err();
93433d6423SLionel Sambuc }
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc /* yes, this is ugly, but not as ugly as repeating it all every time */
96433d6423SLionel Sambuc #define TEST_GETNAMEINFO_ERR_PARAMS ipaddr, port, nodelen, servicelen, flags
97433d6423SLionel Sambuc 
test_getnameinfo_err_nr(int n,unsigned long ipaddr,unsigned short port,socklen_t nodelen,socklen_t servicelen,int flags,int exp_result,int result)98433d6423SLionel Sambuc static void test_getnameinfo_err_nr(
99433d6423SLionel Sambuc 	int n,
100433d6423SLionel Sambuc 	unsigned long ipaddr,
101433d6423SLionel Sambuc 	unsigned short port,
102433d6423SLionel Sambuc 	socklen_t nodelen,
103433d6423SLionel Sambuc 	socklen_t servicelen,
104433d6423SLionel Sambuc 	int flags,
105433d6423SLionel Sambuc 	int exp_result,
106433d6423SLionel Sambuc 	int result)
107433d6423SLionel Sambuc {
108433d6423SLionel Sambuc 	char exp_result_s[23], result_s[23];
109433d6423SLionel Sambuc 
110433d6423SLionel Sambuc 	/* convert result to string */
111433d6423SLionel Sambuc 	snprintf(exp_result_s, sizeof(exp_result_s), "%d/0x%x",
112433d6423SLionel Sambuc 		exp_result, exp_result);
113433d6423SLionel Sambuc 	snprintf(result_s, sizeof(result_s), "%d/0x%x", result, result);
114433d6423SLionel Sambuc 	test_getnameinfo_err(n, TEST_GETNAMEINFO_ERR_PARAMS,
115433d6423SLionel Sambuc 		exp_result_s, result_s);
116433d6423SLionel Sambuc }
117433d6423SLionel Sambuc 
test_getaddrinfo(const char * nodename,int nodename_numerical,const char * servname,int servname_numerical,int passhints,int flags,int family,int socktype,int exp_results,unsigned long exp_ip,int exp_canonname,unsigned short exp_port)118433d6423SLionel Sambuc static void test_getaddrinfo(
119433d6423SLionel Sambuc 	const char *nodename,
120433d6423SLionel Sambuc 	int nodename_numerical,
121433d6423SLionel Sambuc 	const char *servname,
122433d6423SLionel Sambuc 	int servname_numerical,
123433d6423SLionel Sambuc 	int passhints,
124433d6423SLionel Sambuc 	int flags,
125433d6423SLionel Sambuc 	int family,
126433d6423SLionel Sambuc 	int socktype,
127433d6423SLionel Sambuc 	int exp_results,
128433d6423SLionel Sambuc 	unsigned long exp_ip,
129433d6423SLionel Sambuc 	int exp_canonname,
130433d6423SLionel Sambuc 	unsigned short exp_port)
131433d6423SLionel Sambuc {
132433d6423SLionel Sambuc 	struct addrinfo *ai, *ai_cur;
133433d6423SLionel Sambuc 	struct addrinfo hints;
134433d6423SLionel Sambuc 	struct sockaddr_in *sockaddr_in;
135433d6423SLionel Sambuc 	int ai_count_dgram, ai_count_stream, r;
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc 	/* some parameters are only meaningful with hints */
138433d6423SLionel Sambuc 	assert(passhints || !flags);
139433d6423SLionel Sambuc 	assert(passhints || family == AF_UNSPEC);
140433d6423SLionel Sambuc 	assert(passhints || !socktype);
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc 	/* a combination of parameters don't make sense to test */
143433d6423SLionel Sambuc 	if (nodename == NULL && servname == NULL) return;
144433d6423SLionel Sambuc 	if (nodename == NULL && (flags & AI_NUMERICHOST)) return;
145433d6423SLionel Sambuc 	if (servname == NULL && (flags & AI_NUMERICSERV)) return;
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc 	/* initialize hints */
148433d6423SLionel Sambuc 	memset(&hints, 0, sizeof(hints));
149433d6423SLionel Sambuc 	hints.ai_flags = flags;
150433d6423SLionel Sambuc 	hints.ai_family = family;
151433d6423SLionel Sambuc 	hints.ai_socktype = socktype;
152433d6423SLionel Sambuc 
153433d6423SLionel Sambuc 	/* perform query and test result */
154433d6423SLionel Sambuc 	ai = (struct addrinfo *) 0xDEADBEEF;
155433d6423SLionel Sambuc 	r = getaddrinfo(nodename, servname, passhints ? &hints : NULL, &ai);
156433d6423SLionel Sambuc 	if (r < 0 || r >= 32 || !((1 << r) & exp_results))
157433d6423SLionel Sambuc 		test_getaddrinfo_err_nr(1, TEST_GETADDRINFO_ERR_PARAMS, exp_results, r);
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc 	if (r)
160433d6423SLionel Sambuc 		return;
161433d6423SLionel Sambuc 
162433d6423SLionel Sambuc 	/* the function succeeded; do the results make sense? */
163433d6423SLionel Sambuc 	ai_cur = ai;
164433d6423SLionel Sambuc 	ai_count_dgram = 0;
165433d6423SLionel Sambuc 	ai_count_stream = 0;
166433d6423SLionel Sambuc 	while (ai_cur)
167433d6423SLionel Sambuc 	{
168*ad920fc4SDavid van Moolenbroek 		/*
169*ad920fc4SDavid van Moolenbroek 		 * TODO: this test was written for IPv4.  For now, skip IPv6
170*ad920fc4SDavid van Moolenbroek 		 * results altogether.  Later, we should add additional code
171*ad920fc4SDavid van Moolenbroek 		 * for IPv6.  However, since this test now largely exercises
172*ad920fc4SDavid van Moolenbroek 		 * NetBSD code, it is not as important as it once was.
173*ad920fc4SDavid van Moolenbroek 		 */
174*ad920fc4SDavid van Moolenbroek 		if (ai_cur->ai_family == AF_INET6) {
175*ad920fc4SDavid van Moolenbroek 			ai_cur = ai_cur->ai_next;
176*ad920fc4SDavid van Moolenbroek 			continue;
177*ad920fc4SDavid van Moolenbroek 		}
178*ad920fc4SDavid van Moolenbroek 
179433d6423SLionel Sambuc 		/* test result fields */
180433d6423SLionel Sambuc 		if (ai_cur->ai_family != AF_INET)
181433d6423SLionel Sambuc 			test_getaddrinfo_err_nr(2, TEST_GETADDRINFO_ERR_PARAMS,
182433d6423SLionel Sambuc 				AF_INET, ai_cur->ai_family);
183433d6423SLionel Sambuc 
184433d6423SLionel Sambuc 		if (socktype && ai_cur->ai_socktype != socktype)
185433d6423SLionel Sambuc 			test_getaddrinfo_err_nr(3, TEST_GETADDRINFO_ERR_PARAMS,
186433d6423SLionel Sambuc 				socktype, ai_cur->ai_socktype);
187433d6423SLionel Sambuc 
188433d6423SLionel Sambuc 		switch (ai_cur->ai_socktype)
189433d6423SLionel Sambuc 		{
190433d6423SLionel Sambuc 			case SOCK_DGRAM:  ai_count_dgram++;  break;
191433d6423SLionel Sambuc 			case SOCK_STREAM: ai_count_stream++; break;
192433d6423SLionel Sambuc 		}
193433d6423SLionel Sambuc 
194433d6423SLionel Sambuc 		/* do address and port match? */
195433d6423SLionel Sambuc 		if (ai_cur->ai_addrlen != sizeof(struct sockaddr_in))
196433d6423SLionel Sambuc 			test_getaddrinfo_err_nr(4, TEST_GETADDRINFO_ERR_PARAMS,
197433d6423SLionel Sambuc 				sizeof(struct sockaddr_in),
198433d6423SLionel Sambuc 				ai_cur->ai_addrlen);
199433d6423SLionel Sambuc 		else
200433d6423SLionel Sambuc 		{
201433d6423SLionel Sambuc 			sockaddr_in = (struct sockaddr_in *) ai_cur->ai_addr;
202433d6423SLionel Sambuc 			if (sockaddr_in->sin_addr.s_addr != exp_ip)
203433d6423SLionel Sambuc 				test_getaddrinfo_err_nr(5,
204433d6423SLionel Sambuc 					TEST_GETADDRINFO_ERR_PARAMS,
205433d6423SLionel Sambuc 					ntohl(exp_ip),
206433d6423SLionel Sambuc 					ntohl(sockaddr_in->sin_addr.s_addr));
207433d6423SLionel Sambuc 
208433d6423SLionel Sambuc 			if (sockaddr_in->sin_port != exp_port)
209433d6423SLionel Sambuc 				test_getaddrinfo_err_nr(6,
210433d6423SLionel Sambuc 					TEST_GETADDRINFO_ERR_PARAMS,
211433d6423SLionel Sambuc 					ntohs(exp_port),
212433d6423SLionel Sambuc 					ntohs(sockaddr_in->sin_port));
213433d6423SLionel Sambuc 		}
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc 		/* If a hostname is numeric, there can't be a canonical name.
216433d6423SLionel Sambuc 		 * Instead, the returned canonname (if requested) will be
217433d6423SLionel Sambuc 		 * identical to the supplied hostname */
218433d6423SLionel Sambuc 		if (nodename != NULL && nodename_numerical &&
219433d6423SLionel Sambuc 		    (flags & AI_CANONNAME)) {
220433d6423SLionel Sambuc 			if (strncmp(ai_cur->ai_canonname, nodename,
221433d6423SLionel Sambuc 					strlen(nodename)))
222433d6423SLionel Sambuc 			test_getaddrinfo_err(11,
223433d6423SLionel Sambuc 				TEST_GETADDRINFO_ERR_PARAMS,
224433d6423SLionel Sambuc 				nodename, ai_cur->ai_canonname);
225433d6423SLionel Sambuc 		} else {
226433d6423SLionel Sambuc 			/* is canonical supplied? */
227433d6423SLionel Sambuc 			if (exp_canonname && nodename &&
228433d6423SLionel Sambuc 			    (!ai_cur->ai_canonname || !*ai_cur->ai_canonname))
229433d6423SLionel Sambuc 				test_getaddrinfo_err(7,
230433d6423SLionel Sambuc 					TEST_GETADDRINFO_ERR_PARAMS,
231433d6423SLionel Sambuc 					"(anything)", ai_cur->ai_canonname);
232433d6423SLionel Sambuc 
233433d6423SLionel Sambuc 			if (!exp_canonname && ai_cur->ai_canonname)
234433d6423SLionel Sambuc 				test_getaddrinfo_err(8,
235433d6423SLionel Sambuc 					TEST_GETADDRINFO_ERR_PARAMS,
236433d6423SLionel Sambuc 					NULL, ai_cur->ai_canonname);
237433d6423SLionel Sambuc 
238433d6423SLionel Sambuc 		}
239433d6423SLionel Sambuc 		/* move to next result */
240433d6423SLionel Sambuc 		ai_cur = ai_cur->ai_next;
241433d6423SLionel Sambuc 	}
242433d6423SLionel Sambuc 
243433d6423SLionel Sambuc 	/* If socket type is non-zero, make sure we got what we wanted. Else
244433d6423SLionel Sambuc 	 * any result is okay. */
245433d6423SLionel Sambuc 	if (socktype) {
246433d6423SLionel Sambuc 		if (ai_count_dgram != ((socktype == SOCK_STREAM) ? 0 : 1))
247433d6423SLionel Sambuc 			test_getaddrinfo_err_nr(9, TEST_GETADDRINFO_ERR_PARAMS,
248433d6423SLionel Sambuc 			(socktype == SOCK_STREAM) ? 0 : 1, ai_count_dgram);
249433d6423SLionel Sambuc 
250433d6423SLionel Sambuc 		if (ai_count_stream != ((socktype == SOCK_DGRAM) ? 0 : 1))
251433d6423SLionel Sambuc 			test_getaddrinfo_err_nr(10, TEST_GETADDRINFO_ERR_PARAMS,
252433d6423SLionel Sambuc 			(socktype == SOCK_DGRAM) ? 0 : 1, ai_count_stream);
253433d6423SLionel Sambuc 	}
254433d6423SLionel Sambuc 
255433d6423SLionel Sambuc 	/* clean up */
256433d6423SLionel Sambuc 	freeaddrinfo(ai);
257433d6423SLionel Sambuc }
258433d6423SLionel Sambuc 
memsetl(void * s,unsigned long c,size_t n)259433d6423SLionel Sambuc static void memsetl(void *s, unsigned long c, size_t n)
260433d6423SLionel Sambuc {
261433d6423SLionel Sambuc 	unsigned char *p = (unsigned char *) s;
262433d6423SLionel Sambuc 	size_t i;
263433d6423SLionel Sambuc 
264433d6423SLionel Sambuc 	for (i = 0; i < n; i++)
265433d6423SLionel Sambuc 		p[i] = c >> (8 * (i % sizeof(c)));
266433d6423SLionel Sambuc }
267433d6423SLionel Sambuc 
test_getnameinfo(unsigned long ipaddr,unsigned short port,const char * exp_node,socklen_t nodelen,const char * exp_service,socklen_t servicelen,int flags,int exp_results)268433d6423SLionel Sambuc static void test_getnameinfo(
269433d6423SLionel Sambuc 	unsigned long ipaddr,
270433d6423SLionel Sambuc 	unsigned short port,
271433d6423SLionel Sambuc 	const char *exp_node,
272433d6423SLionel Sambuc 	socklen_t nodelen,
273433d6423SLionel Sambuc 	const char *exp_service,
274433d6423SLionel Sambuc 	socklen_t servicelen,
275433d6423SLionel Sambuc 	int flags,
276433d6423SLionel Sambuc 	int exp_results)
277433d6423SLionel Sambuc {
278433d6423SLionel Sambuc 	struct sockaddr_in sockaddr;
279433d6423SLionel Sambuc 	char node[256], service[256];
280433d6423SLionel Sambuc 	int r;
281433d6423SLionel Sambuc 
282433d6423SLionel Sambuc 	/* avoid buffer overflows */
283433d6423SLionel Sambuc 	assert(nodelen <= sizeof(node));
284433d6423SLionel Sambuc 	assert(servicelen <= sizeof(service));
285433d6423SLionel Sambuc 
286433d6423SLionel Sambuc 	/* perform query and test result */
287433d6423SLionel Sambuc 	sockaddr.sin_family = AF_INET;
288433d6423SLionel Sambuc 	sockaddr.sin_addr.s_addr = ipaddr;
289433d6423SLionel Sambuc 	sockaddr.sin_port = port;
290433d6423SLionel Sambuc 	memsetl(node, 0xDEADBEEF, nodelen);
291433d6423SLionel Sambuc 	memsetl(service, 0xDEADBEEF, servicelen);
292433d6423SLionel Sambuc 	r = getnameinfo((struct sockaddr *) &sockaddr, sizeof(sockaddr),
293433d6423SLionel Sambuc 		node, nodelen, service, servicelen, flags);
294433d6423SLionel Sambuc 
295433d6423SLionel Sambuc 	if (r < 0 || r >= 32 || !((1 << r) & exp_results))
296433d6423SLionel Sambuc 		test_getnameinfo_err_nr(1, TEST_GETNAMEINFO_ERR_PARAMS,
297433d6423SLionel Sambuc 			exp_results, r);
298433d6423SLionel Sambuc 
299433d6423SLionel Sambuc 	if (r)
300433d6423SLionel Sambuc 		return;
301433d6423SLionel Sambuc 
302433d6423SLionel Sambuc 	/* check results */
303433d6423SLionel Sambuc 	if (nodelen && strcmp(exp_node, node) != 0)
304433d6423SLionel Sambuc 		test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
305433d6423SLionel Sambuc 			exp_node, node);
306433d6423SLionel Sambuc 
307433d6423SLionel Sambuc 	if (servicelen && strcmp(exp_service, service) != 0)
308433d6423SLionel Sambuc 		test_getnameinfo_err(2, TEST_GETNAMEINFO_ERR_PARAMS,
309433d6423SLionel Sambuc 			exp_service, service);
310433d6423SLionel Sambuc }
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc static struct
313433d6423SLionel Sambuc {
314433d6423SLionel Sambuc 	const char *nodename;
315433d6423SLionel Sambuc 	unsigned long ipaddr;
316433d6423SLionel Sambuc 	int numeric;
317433d6423SLionel Sambuc 	int canonname;
318433d6423SLionel Sambuc 	int need_network;
319433d6423SLionel Sambuc 	int exp_result;
320433d6423SLionel Sambuc } hosts[] = {
321433d6423SLionel Sambuc 	{ NULL,             0x7f000001, 1, 1, 0, 0                 },
322433d6423SLionel Sambuc 	{ "0.0.0.0",        0x00000000, 1, 0, 0, 0                 },
323433d6423SLionel Sambuc 	{ "0.0.0.255",      0x000000ff, 1, 0, 0, 0                 },
324433d6423SLionel Sambuc 	{ "0.0.255.0",      0x0000ff00, 1, 0, 0, 0                 },
325433d6423SLionel Sambuc 	{ "0.255.0.0",      0x00ff0000, 1, 0, 0, 0                 },
326433d6423SLionel Sambuc 	{ "255.0.0.0",      0xff000000, 1, 0, 0, 0                 },
327433d6423SLionel Sambuc 	{ "127.0.0.1",      0x7f000001, 1, 0, 0, 0                 },
328433d6423SLionel Sambuc 	{ "localhost",      0x7f000001, 0, 1, 0, 0,                },
3294d5b0de1SErik van der Kouwe 	{ "test48.minix3.org", 0x7f010203, 0, 1, 1, 0,             },
3302909efcbSBen Gras 	{ "minix3.example.com",     0x00000000, 0, 0, 1, (1<<EAI_NONAME)|(1<<EAI_FAIL)|(1<<EAI_NODATA)}};
331433d6423SLionel Sambuc 
332433d6423SLionel Sambuc static struct
333433d6423SLionel Sambuc {
334433d6423SLionel Sambuc 	const char *servname;
335433d6423SLionel Sambuc 	unsigned short port;
336433d6423SLionel Sambuc 	int numeric;
337433d6423SLionel Sambuc 	int socktype;
338433d6423SLionel Sambuc 	int exp_result;
339433d6423SLionel Sambuc } services[] = {
340433d6423SLionel Sambuc 	{ NULL,        0, 1, 0,           0                  },
341433d6423SLionel Sambuc 	{ "0",         0, 1, 0,           0                  },
342433d6423SLionel Sambuc 	{ "1",         1, 1, 0,           0                  },
343433d6423SLionel Sambuc 	{ "32767", 32767, 1, 0,           0                  },
344433d6423SLionel Sambuc 	{ "32768", 32768, 1, 0,           0                  },
345433d6423SLionel Sambuc 	{ "65535", 65535, 1, 0,           0                  },
346433d6423SLionel Sambuc 	{ "echo",      7, 0, 0,           0                  },
347433d6423SLionel Sambuc 	{ "ftp",      21, 0, 0, 0                  },
348433d6423SLionel Sambuc 	{ "tftp",     69, 0, 0, 0                  },
349433d6423SLionel Sambuc 	{ "-1",        0, 1, 0,           (1<<EAI_NONAME) | (1<<EAI_SERVICE) },
350433d6423SLionel Sambuc 	{ "",          0, 1, 0,           (1<<EAI_NONAME) | (1<<EAI_SERVICE) },
351433d6423SLionel Sambuc 	{ "65537",     0, 1, 0,           (1 << EAI_SERVICE) },
352433d6423SLionel Sambuc 	{ "XXX",       0, 0, 0,           (1 << EAI_SERVICE) }};
353433d6423SLionel Sambuc 
354433d6423SLionel Sambuc static struct
355433d6423SLionel Sambuc {
356433d6423SLionel Sambuc 	int value;
357433d6423SLionel Sambuc 	int exp_result;
358433d6423SLionel Sambuc } families[] = {
359433d6423SLionel Sambuc 	{ AF_UNSPEC,               0                 },
360433d6423SLionel Sambuc 	{ AF_INET,                 0                 },
361433d6423SLionel Sambuc 	{ AF_UNSPEC + AF_INET + 1, (1 << EAI_FAMILY)    }};
362433d6423SLionel Sambuc 
363433d6423SLionel Sambuc static struct
364433d6423SLionel Sambuc {
365433d6423SLionel Sambuc 	int value;
366433d6423SLionel Sambuc 	int exp_result;
367433d6423SLionel Sambuc } socktypes[] = {
368433d6423SLionel Sambuc 	{ 0,                            0                   },
369433d6423SLionel Sambuc 	{ SOCK_STREAM,                  0                   },
370433d6423SLionel Sambuc 	{ SOCK_DGRAM,                   0                   },
371433d6423SLionel Sambuc 	{ SOCK_STREAM + SOCK_DGRAM + 1,
372433d6423SLionel Sambuc 		(1 << EAI_SOCKTYPE) | (1 << EAI_FAIL) | (1 << EAI_NONAME) }};
373433d6423SLionel Sambuc 
374433d6423SLionel Sambuc #define LENGTH(a) (sizeof((a)) / sizeof((a)[0]))
375433d6423SLionel Sambuc 
test_getaddrinfo_all(int use_network)376433d6423SLionel Sambuc static void test_getaddrinfo_all(int use_network)
377433d6423SLionel Sambuc {
378433d6423SLionel Sambuc 	int flag_PASSIVE, flag_CANONNAME, flag_NUMERICHOST, flag_NUMERICSERV;
3793e8d796eSErik van der Kouwe 	int exp_results, flags, flagcount, i, j, k, l, passhints;
380433d6423SLionel Sambuc 	unsigned long ipaddr;
381433d6423SLionel Sambuc 
382433d6423SLionel Sambuc 	/* loop through various parameter values */
383433d6423SLionel Sambuc 	for (i = 0; i < LENGTH(hosts);     i++)
384433d6423SLionel Sambuc 	for (j = 0; j < LENGTH(services);  j++)
385433d6423SLionel Sambuc 	for (k = 0; k < LENGTH(families);  k++)
386433d6423SLionel Sambuc 	for (l = 0; l < LENGTH(socktypes); l++)
387433d6423SLionel Sambuc 	for (flag_PASSIVE     = 0; flag_PASSIVE < 2;     flag_PASSIVE++)
388433d6423SLionel Sambuc 	for (flag_CANONNAME   = 0; flag_CANONNAME < 2;   flag_CANONNAME++)
389433d6423SLionel Sambuc 	for (flag_NUMERICHOST = 0; flag_NUMERICHOST < 2; flag_NUMERICHOST++)
390433d6423SLionel Sambuc 	for (flag_NUMERICSERV = 0; flag_NUMERICSERV < 2; flag_NUMERICSERV++)
391433d6423SLionel Sambuc 	for (passhints = 0; passhints < 2; passhints++)
392433d6423SLionel Sambuc 	{
3933e8d796eSErik van der Kouwe 		/* skip some redundant combinations */
3943e8d796eSErik van der Kouwe 		flagcount = flag_PASSIVE + flag_CANONNAME +
3953e8d796eSErik van der Kouwe 			flag_NUMERICHOST + flag_NUMERICSERV;
3963e8d796eSErik van der Kouwe 		if (flagcount > 1 && flagcount < 4) continue;
3973e8d796eSErik van der Kouwe 
398433d6423SLionel Sambuc 		/* skip tests that need but cannot use network */
399433d6423SLionel Sambuc 		if (!use_network && hosts[i].need_network)
400433d6423SLionel Sambuc 			continue;
401433d6423SLionel Sambuc 
402433d6423SLionel Sambuc 		/* determine flags */
403433d6423SLionel Sambuc 		flags = (flag_PASSIVE     ? AI_PASSIVE : 0) |
404433d6423SLionel Sambuc 			(flag_CANONNAME   ? AI_CANONNAME : 0) |
405433d6423SLionel Sambuc 			(flag_NUMERICHOST ? AI_NUMERICHOST : 0) |
406433d6423SLionel Sambuc 			(flag_NUMERICSERV ? AI_NUMERICSERV : 0);
407433d6423SLionel Sambuc 
408433d6423SLionel Sambuc 		/* some options require hints */
409433d6423SLionel Sambuc 		if (families[k].value != AF_UNSPEC ||
410433d6423SLionel Sambuc 		    socktypes[l].value != 0 || flags)  {
411433d6423SLionel Sambuc 			passhints = 1;
412433d6423SLionel Sambuc 		}
413433d6423SLionel Sambuc 
414433d6423SLionel Sambuc 		/* flags may influence IP address */
415433d6423SLionel Sambuc 		ipaddr = hosts[i].ipaddr;
416433d6423SLionel Sambuc 		if (!hosts[i].nodename && flag_PASSIVE)
417433d6423SLionel Sambuc 			ipaddr = INADDR_ANY;
418433d6423SLionel Sambuc 
419433d6423SLionel Sambuc 		/* determine expected result */
420433d6423SLionel Sambuc 		exp_results =
421433d6423SLionel Sambuc 			hosts[i].exp_result |
422433d6423SLionel Sambuc 			services[j].exp_result |
423433d6423SLionel Sambuc 			families[k].exp_result |
424433d6423SLionel Sambuc 			socktypes[l].exp_result;
425433d6423SLionel Sambuc 		if (!hosts[i].nodename && !services[j].servname)
426433d6423SLionel Sambuc 			exp_results |= (1 << EAI_NONAME);
427433d6423SLionel Sambuc 
428433d6423SLionel Sambuc 		if (flag_NUMERICHOST && !hosts[i].numeric)
429433d6423SLionel Sambuc 			exp_results |= (1 << EAI_NONAME);
430433d6423SLionel Sambuc 
431433d6423SLionel Sambuc 		if (flag_NUMERICSERV && !services[j].numeric)
432433d6423SLionel Sambuc 			exp_results |= (1 << EAI_NONAME);
433433d6423SLionel Sambuc 
434433d6423SLionel Sambuc 		/* When we don't pass hints, getaddrinfo will find suitable
435433d6423SLionel Sambuc 		 * settings for us. If we do pass hints, there might be
436433d6423SLionel Sambuc 		 * conflicts.
437433d6423SLionel Sambuc 		 */
438433d6423SLionel Sambuc 		if (passhints) {
439433d6423SLionel Sambuc 			/* Can't have conflicting socket types */
440433d6423SLionel Sambuc 			if (services[j].socktype &&
441433d6423SLionel Sambuc 			    socktypes[l].value &&
442433d6423SLionel Sambuc 			    socktypes[l].value != services[j].socktype) {
443433d6423SLionel Sambuc 				exp_results |= (1 << EAI_SERVICE);
444433d6423SLionel Sambuc 			}
445433d6423SLionel Sambuc 		}
446433d6423SLionel Sambuc 
447433d6423SLionel Sambuc 		/* with no reason for failure, we demand success */
448433d6423SLionel Sambuc 		if (!exp_results)
449433d6423SLionel Sambuc 			exp_results |= (1 << 0);
450433d6423SLionel Sambuc 
451433d6423SLionel Sambuc 		/* test getaddrinfo function */
452433d6423SLionel Sambuc 		test_getaddrinfo(
453433d6423SLionel Sambuc 			hosts[i].nodename,
454433d6423SLionel Sambuc 			hosts[i].numeric,
455433d6423SLionel Sambuc 			services[j].servname,
456433d6423SLionel Sambuc 			services[j].numeric,
457433d6423SLionel Sambuc 			passhints,
458433d6423SLionel Sambuc 			flags,
459433d6423SLionel Sambuc 			families[k].value,
460433d6423SLionel Sambuc 			socktypes[l].value,
461433d6423SLionel Sambuc 			exp_results,
462433d6423SLionel Sambuc 			htonl(ipaddr),
463433d6423SLionel Sambuc 			flag_CANONNAME && hosts[i].canonname,
464433d6423SLionel Sambuc 			htons(services[j].port));
465433d6423SLionel Sambuc 	}
466433d6423SLionel Sambuc }
467433d6423SLionel Sambuc 
468433d6423SLionel Sambuc static struct
469433d6423SLionel Sambuc {
470433d6423SLionel Sambuc 	const char *nodename;
471433d6423SLionel Sambuc 	const char *nodenum;
472433d6423SLionel Sambuc 	unsigned long ipaddr;
473433d6423SLionel Sambuc 	int havename;
474433d6423SLionel Sambuc } ipaddrs[] = {
475433d6423SLionel Sambuc 	{ "0.0.0.0",    "0.0.0.0",      0x00000000, 0 },
476433d6423SLionel Sambuc 	{ "0.0.0.255",  "0.0.0.255",    0x000000ff, 0 },
477433d6423SLionel Sambuc 	{ "0.0.255.0",  "0.0.255.0",    0x0000ff00, 0 },
478433d6423SLionel Sambuc 	{ "0.255.0.0",  "0.255.0.0",    0x00ff0000, 0 },
479433d6423SLionel Sambuc 	{ "255.0.0.0",  "255.0.0.0",    0xff000000, 0 },
480433d6423SLionel Sambuc 	{ "localhost",  "127.0.0.1",    0x7f000001, 1 },
481433d6423SLionel Sambuc 	/* no reverse DNS unfortunately */
482433d6423SLionel Sambuc 	/* { "minix3.org", "130.37.20.20", 0x82251414, 1 } */};
483433d6423SLionel Sambuc 
484433d6423SLionel Sambuc static struct
485433d6423SLionel Sambuc {
486433d6423SLionel Sambuc 	const char *servname;
487433d6423SLionel Sambuc 	const char *servnum;
488433d6423SLionel Sambuc 	unsigned short port;
489433d6423SLionel Sambuc 	int socktype;
490433d6423SLionel Sambuc 	struct servent *se_tcp; /* getservbyport() s_name on this port with "tcp" */
491433d6423SLionel Sambuc 	struct servent *se_udp; /* getservbyport() s_name on this port with "udp" */
492433d6423SLionel Sambuc } ports[] = {
493433d6423SLionel Sambuc 	{ "0",      "0",         0, 0           },
494433d6423SLionel Sambuc 	{ "tcpmux", "1",         1, SOCK_STREAM },
495433d6423SLionel Sambuc 	{ "32767",  "32767", 32767, 0           },
496433d6423SLionel Sambuc 	{ "32768",  "32768", 32768, 0           },
497433d6423SLionel Sambuc 	{ "65535",  "65535", 65535, 0           },
498433d6423SLionel Sambuc 	{ "echo",   "7",         7, 0           },
499433d6423SLionel Sambuc 	{ "ftp",    "21",       21, SOCK_STREAM },
500433d6423SLionel Sambuc 	{ "tftp",   "69",       69, SOCK_DGRAM  }};
501433d6423SLionel Sambuc 
502433d6423SLionel Sambuc static int buflens[] = { 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 255 };
503433d6423SLionel Sambuc 
test_getnameinfo_all(void)504433d6423SLionel Sambuc static void test_getnameinfo_all(void)
505433d6423SLionel Sambuc {
506433d6423SLionel Sambuc 	int flag_NUMERICHOST, flag_NAMEREQD, flag_NUMERICSERV, flag_DGRAM;
5073083d603SDavid van Moolenbroek 	int exp_results, flagcount, flags, i, j, k, l;
508433d6423SLionel Sambuc 	const char *nodename, *servname;
509433d6423SLionel Sambuc 
510433d6423SLionel Sambuc 	/* set ports servent structs */
511433d6423SLionel Sambuc 	for (j = 0; j < LENGTH(ports);   j++) {
512433d6423SLionel Sambuc 		struct servent *se_tcp, *se_udp;
513433d6423SLionel Sambuc 
514433d6423SLionel Sambuc 		se_tcp = getservbyport(htons(ports[j].port), "tcp");
515433d6423SLionel Sambuc 		ports[j].se_tcp = se_tcp;
516433d6423SLionel Sambuc 
517433d6423SLionel Sambuc 		if(ports[j].se_tcp) {
518433d6423SLionel Sambuc 			ports[j].se_tcp = malloc(sizeof(struct servent));
519433d6423SLionel Sambuc 			memcpy(ports[j].se_tcp, se_tcp, sizeof(*se_tcp));
520433d6423SLionel Sambuc 			assert(ports[j].se_tcp->s_name);
521433d6423SLionel Sambuc 			ports[j].se_tcp->s_name = strdup(ports[j].se_tcp->s_name);
522433d6423SLionel Sambuc 			assert(ports[j].se_tcp->s_name);
523433d6423SLionel Sambuc 		}
524433d6423SLionel Sambuc 
525433d6423SLionel Sambuc 		se_udp = getservbyport(htons(ports[j].port), "udp");
526433d6423SLionel Sambuc 		ports[j].se_udp = se_udp;
527433d6423SLionel Sambuc 
528433d6423SLionel Sambuc 		if(ports[j].se_udp) {
529433d6423SLionel Sambuc 			ports[j].se_udp = malloc(sizeof(struct servent));
530433d6423SLionel Sambuc 			memcpy(ports[j].se_udp, se_udp, sizeof(*se_udp));
531433d6423SLionel Sambuc 			assert(ports[j].se_udp->s_name);
532433d6423SLionel Sambuc 			ports[j].se_udp->s_name = strdup(ports[j].se_udp->s_name);
533433d6423SLionel Sambuc 			assert(ports[j].se_udp->s_name);
534433d6423SLionel Sambuc 		}
535433d6423SLionel Sambuc 	}
536433d6423SLionel Sambuc 
537433d6423SLionel Sambuc 	/* loop through various parameter values */
538433d6423SLionel Sambuc 	for (i = 0; i < LENGTH(ipaddrs); i++)
539433d6423SLionel Sambuc 	for (j = 0; j < LENGTH(ports);   j++)
540433d6423SLionel Sambuc 	for (k = 0; k < LENGTH(buflens); k++)
541433d6423SLionel Sambuc 	for (l = 0; l < LENGTH(buflens); l++)
542433d6423SLionel Sambuc 	for (flag_NUMERICHOST = 0; flag_NUMERICHOST < 2; flag_NUMERICHOST++)
543433d6423SLionel Sambuc 	for (flag_NAMEREQD    = 0; flag_NAMEREQD < 2;    flag_NAMEREQD++)
544433d6423SLionel Sambuc 	for (flag_NUMERICSERV = 0; flag_NUMERICSERV < 2; flag_NUMERICSERV++)
545433d6423SLionel Sambuc 	for (flag_DGRAM       = 0; flag_DGRAM < 2;       flag_DGRAM++)
546433d6423SLionel Sambuc 	{
5473e8d796eSErik van der Kouwe 		/* skip some redundant combinations */
5483e8d796eSErik van der Kouwe 		flagcount = flag_NUMERICHOST + flag_NAMEREQD +
5493e8d796eSErik van der Kouwe 			flag_NUMERICSERV + flag_DGRAM;
5503e8d796eSErik van der Kouwe 		if (flagcount > 1 && flagcount < 4) continue;
5513e8d796eSErik van der Kouwe 		if (k > 1 && k < LENGTH(buflens) - 2 &&
5523e8d796eSErik van der Kouwe 			l > 1 && l < LENGTH(buflens) - 2) continue;
5533e8d796eSErik van der Kouwe 
554433d6423SLionel Sambuc 		/* determine flags */
555433d6423SLionel Sambuc 		flags = (flag_NUMERICHOST ? NI_NUMERICHOST : 0) |
556433d6423SLionel Sambuc 			(flag_NAMEREQD    ? NI_NAMEREQD : 0) |
557433d6423SLionel Sambuc 			(flag_NUMERICSERV ? NI_NUMERICSERV : 0) |
558433d6423SLionel Sambuc 			(flag_DGRAM       ? NI_DGRAM : 0);
559433d6423SLionel Sambuc 
560433d6423SLionel Sambuc 		/* determine expected result */
561433d6423SLionel Sambuc 		exp_results = 0;
562433d6423SLionel Sambuc 
563433d6423SLionel Sambuc 		nodename = flag_NUMERICHOST ? ipaddrs[i].nodenum : ipaddrs[i].nodename;
564433d6423SLionel Sambuc 		if (buflens[k] > 0 && buflens[k] <= strlen(nodename))
565433d6423SLionel Sambuc 			exp_results |= (1 << EAI_OVERFLOW) | (1 << EAI_MEMORY);
566433d6423SLionel Sambuc 
567433d6423SLionel Sambuc 		struct servent *se = flag_DGRAM ? ports[j].se_udp : ports[j].se_tcp;
568433d6423SLionel Sambuc 
569433d6423SLionel Sambuc 		servname = (flag_NUMERICSERV) ?
570433d6423SLionel Sambuc 			ports[j].servnum : (se ? se->s_name : ports[j].servname);
571433d6423SLionel Sambuc 
572433d6423SLionel Sambuc 		if (buflens[l] > 0 && buflens[l] <= strlen(servname))
573433d6423SLionel Sambuc 			exp_results |= (1 << EAI_OVERFLOW) | (1 << EAI_MEMORY);
574433d6423SLionel Sambuc 
575433d6423SLionel Sambuc 		if (flag_NAMEREQD && (!ipaddrs[i].havename || flag_NUMERICHOST) && buflens[k])
576433d6423SLionel Sambuc 			exp_results |= (1 << EAI_NONAME);
577433d6423SLionel Sambuc 
578433d6423SLionel Sambuc 		/* with no reason for failure, we demand success */
579433d6423SLionel Sambuc 		if (!exp_results)
580433d6423SLionel Sambuc 			exp_results |= (1 << 0);
581433d6423SLionel Sambuc 
582433d6423SLionel Sambuc 		/* perform the test */
583433d6423SLionel Sambuc 		test_getnameinfo(
584433d6423SLionel Sambuc 			htonl(ipaddrs[i].ipaddr),
585433d6423SLionel Sambuc 			htons(ports[j].port),
586433d6423SLionel Sambuc 			nodename,
587433d6423SLionel Sambuc 			buflens[k],
588433d6423SLionel Sambuc 			servname,
589433d6423SLionel Sambuc 			buflens[l],
590433d6423SLionel Sambuc 			flags,
591433d6423SLionel Sambuc 			exp_results);
592433d6423SLionel Sambuc 	}
593433d6423SLionel Sambuc }
594433d6423SLionel Sambuc 
main(void)595433d6423SLionel Sambuc int main(void)
596433d6423SLionel Sambuc {
597433d6423SLionel Sambuc 	int use_network;
598433d6423SLionel Sambuc 
599433d6423SLionel Sambuc 	start(48);
600433d6423SLionel Sambuc 
6013433559cSErik van der Kouwe 	use_network = get_setting_use_network();
602433d6423SLionel Sambuc 	test_getaddrinfo_all(use_network);
603433d6423SLionel Sambuc 	test_getnameinfo_all();
604433d6423SLionel Sambuc 
605433d6423SLionel Sambuc 	quit();
606433d6423SLionel Sambuc 	return 0;
607433d6423SLionel Sambuc }
608