xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/roken/test-mini_inetd.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: test-mini_inetd.c,v 1.2 2017/01/28 21:31:50 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /***********************************************************************
4ca1c9b0cSelric  * Copyright (c) 2009, Secure Endpoints Inc.
5ca1c9b0cSelric  * All rights reserved.
6ca1c9b0cSelric  *
7ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
8ca1c9b0cSelric  * modification, are permitted provided that the following conditions
9ca1c9b0cSelric  * are met:
10ca1c9b0cSelric  *
11ca1c9b0cSelric  * - Redistributions of source code must retain the above copyright
12ca1c9b0cSelric  *   notice, this list of conditions and the following disclaimer.
13ca1c9b0cSelric  *
14ca1c9b0cSelric  * - Redistributions in binary form must reproduce the above copyright
15ca1c9b0cSelric  *   notice, this list of conditions and the following disclaimer in
16ca1c9b0cSelric  *   the documentation and/or other materials provided with the
17ca1c9b0cSelric  *   distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20ca1c9b0cSelric  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21ca1c9b0cSelric  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22ca1c9b0cSelric  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23ca1c9b0cSelric  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24ca1c9b0cSelric  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25ca1c9b0cSelric  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26ca1c9b0cSelric  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28ca1c9b0cSelric  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29ca1c9b0cSelric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30ca1c9b0cSelric  * OF THE POSSIBILITY OF SUCH DAMAGE.
31ca1c9b0cSelric  *
32ca1c9b0cSelric  **********************************************************************/
33ca1c9b0cSelric 
34ca1c9b0cSelric #include <config.h>
35ca1c9b0cSelric #include <krb5/roken.h>
36ca1c9b0cSelric #include <stdio.h>
37ca1c9b0cSelric #include <string.h>
38ca1c9b0cSelric #include <stdlib.h>
39ca1c9b0cSelric 
40ca1c9b0cSelric #define PORT 8013
41ca1c9b0cSelric #define PORT_S "8013"
42ca1c9b0cSelric 
43ca1c9b0cSelric char * prog = "Master";
44ca1c9b0cSelric int is_client = 0;
45ca1c9b0cSelric 
46ca1c9b0cSelric static int
get_address(int flags,struct addrinfo ** ret)47ca1c9b0cSelric get_address(int flags, struct addrinfo ** ret)
48ca1c9b0cSelric {
49ca1c9b0cSelric     struct addrinfo ai;
50ca1c9b0cSelric     int rv;
51ca1c9b0cSelric 
52ca1c9b0cSelric     memset(&ai, 0, sizeof(ai));
53ca1c9b0cSelric 
54ca1c9b0cSelric     ai.ai_flags = flags | AI_NUMERICHOST;
55ca1c9b0cSelric     ai.ai_family = AF_INET;
56ca1c9b0cSelric     ai.ai_socktype = SOCK_STREAM;
57ca1c9b0cSelric     ai.ai_protocol = PF_UNSPEC;
58ca1c9b0cSelric 
59ca1c9b0cSelric     rv = getaddrinfo("127.0.0.1", PORT_S, &ai, ret);
60ca1c9b0cSelric     if (rv)
61ca1c9b0cSelric 	warnx("getaddrinfo: %s", gai_strerror(rv));
62ca1c9b0cSelric     return rv;
63ca1c9b0cSelric }
64ca1c9b0cSelric 
65ca1c9b0cSelric static int
get_connected_socket(rk_socket_t * s_ret)66ca1c9b0cSelric get_connected_socket(rk_socket_t * s_ret)
67ca1c9b0cSelric {
68ca1c9b0cSelric     struct addrinfo * ai = NULL;
69ca1c9b0cSelric     int rv = 0;
70ca1c9b0cSelric     rk_socket_t s = rk_INVALID_SOCKET;
71ca1c9b0cSelric 
72ca1c9b0cSelric     rv = get_address(0, &ai);
73ca1c9b0cSelric     if (rv)
74ca1c9b0cSelric 	return rv;
75ca1c9b0cSelric 
76ca1c9b0cSelric     s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
77ca1c9b0cSelric     if (rk_IS_BAD_SOCKET(s)) {
78ca1c9b0cSelric 	rv = 1;
79ca1c9b0cSelric 	goto done;
80ca1c9b0cSelric     }
81ca1c9b0cSelric 
82ca1c9b0cSelric     rv = connect(s, ai->ai_addr, ai->ai_addrlen);
83ca1c9b0cSelric     if (rk_IS_SOCKET_ERROR(rv))
84ca1c9b0cSelric 	goto done;
85ca1c9b0cSelric 
86ca1c9b0cSelric     *s_ret = s;
87ca1c9b0cSelric     s = rk_INVALID_SOCKET;
88ca1c9b0cSelric     rv = 0;
89ca1c9b0cSelric 
90ca1c9b0cSelric  done:
91ca1c9b0cSelric     if (!rk_IS_BAD_SOCKET(s))
92ca1c9b0cSelric 	rk_closesocket(s);
93ca1c9b0cSelric 
94ca1c9b0cSelric     if (ai)
95ca1c9b0cSelric 	freeaddrinfo(ai);
96ca1c9b0cSelric 
97ca1c9b0cSelric     return (rv) ? rk_SOCK_ERRNO : 0;
98ca1c9b0cSelric }
99ca1c9b0cSelric 
100ca1c9b0cSelric const char * test_strings[] = {
101ca1c9b0cSelric     "Hello",
102ca1c9b0cSelric     "01234566789012345689012345678901234567890123456789",
103ca1c9b0cSelric     "Another test",
104ca1c9b0cSelric     "exit"
105ca1c9b0cSelric };
106ca1c9b0cSelric 
107ca1c9b0cSelric static int
test_simple_echo_client(void)108ca1c9b0cSelric test_simple_echo_client(void)
109ca1c9b0cSelric {
110ca1c9b0cSelric     rk_socket_t s = rk_INVALID_SOCKET;
111ca1c9b0cSelric     int rv;
112ca1c9b0cSelric     char buf[81];
113ca1c9b0cSelric     int i;
114ca1c9b0cSelric 
115ca1c9b0cSelric     fprintf(stderr, "[%s] Getting connected socket...", getprogname());
116ca1c9b0cSelric     rv = get_connected_socket(&s);
117ca1c9b0cSelric     if (rv) {
118ca1c9b0cSelric 	fprintf(stderr, "\n[%s] get_connected_socket() failed (%s)\n",
119ca1c9b0cSelric 		getprogname(), strerror(rk_SOCK_ERRNO));
120ca1c9b0cSelric 	return 1;
121ca1c9b0cSelric     }
122ca1c9b0cSelric 
123ca1c9b0cSelric     fprintf(stderr, "[%s] done\n", getprogname());
124ca1c9b0cSelric 
125ca1c9b0cSelric     for (i=0; i < sizeof(test_strings)/sizeof(test_strings[0]); i++) {
126ca1c9b0cSelric 	rv = send(s, test_strings[i], strlen(test_strings[i]), 0);
127ca1c9b0cSelric 	if (rk_IS_SOCKET_ERROR(rv)) {
128ca1c9b0cSelric 	    fprintf(stderr, "[%s] send() failure (%s)\n",
129ca1c9b0cSelric 		    getprogname(), strerror(rk_SOCK_ERRNO));
130ca1c9b0cSelric 	    rk_closesocket(s);
131ca1c9b0cSelric 	    return 1;
132ca1c9b0cSelric 	}
133ca1c9b0cSelric 
134ca1c9b0cSelric 	rv = recv(s, buf, sizeof(buf), 0);
135ca1c9b0cSelric 	if (rk_IS_SOCKET_ERROR(rv)) {
136ca1c9b0cSelric 	    fprintf (stderr, "[%s] recv() failure (%s)\n",
137ca1c9b0cSelric 		     getprogname(), strerror(rk_SOCK_ERRNO));
138ca1c9b0cSelric 	    rk_closesocket(s);
139ca1c9b0cSelric 	    return 1;
140ca1c9b0cSelric 	}
141ca1c9b0cSelric 
142ca1c9b0cSelric 	if (rv == 0) {
143ca1c9b0cSelric 	    fprintf (stderr, "[%s] No data received\n", prog);
144ca1c9b0cSelric 	    rk_closesocket(s);
145ca1c9b0cSelric 	    return 1;
146ca1c9b0cSelric 	}
147ca1c9b0cSelric 
148ca1c9b0cSelric 	if (rv != strlen(test_strings[i])) {
149ca1c9b0cSelric 	    fprintf (stderr, "[%s] Data length mismatch %d != %d\n", prog, rv, strlen(test_strings[i]));
150ca1c9b0cSelric 	    rk_closesocket(s);
151ca1c9b0cSelric 	    return 1;
152ca1c9b0cSelric 	}
153ca1c9b0cSelric     }
154ca1c9b0cSelric 
155ca1c9b0cSelric     fprintf (stderr, "[%s] Done\n", prog);
156ca1c9b0cSelric     rk_closesocket(s);
157ca1c9b0cSelric     return 0;
158ca1c9b0cSelric }
159ca1c9b0cSelric 
160ca1c9b0cSelric static int
test_simple_echo_socket(void)161ca1c9b0cSelric test_simple_echo_socket(void)
162ca1c9b0cSelric {
163ca1c9b0cSelric     fprintf (stderr, "[%s] Process ID %d\n", prog, GetCurrentProcessId());
164ca1c9b0cSelric     fprintf (stderr, "[%s] Starting echo test with sockets\n", prog);
165ca1c9b0cSelric 
166ca1c9b0cSelric     if (is_client) {
167ca1c9b0cSelric 	return test_simple_echo_client();
168ca1c9b0cSelric     } else {
169ca1c9b0cSelric 
170ca1c9b0cSelric 	rk_socket_t s = rk_INVALID_SOCKET;
171ca1c9b0cSelric 
172ca1c9b0cSelric 	fprintf (stderr, "[%s] Listening for connections...\n", prog);
173ca1c9b0cSelric 	mini_inetd(htons(PORT), &s);
174ca1c9b0cSelric 	if (rk_IS_BAD_SOCKET(s)) {
175ca1c9b0cSelric 	    fprintf (stderr, "[%s] Connect failed (%s)\n",
176ca1c9b0cSelric 		     getprogname(), strerror(rk_SOCK_ERRNO));
177ca1c9b0cSelric 	} else {
178ca1c9b0cSelric 	    fprintf (stderr, "[%s] Connected\n", prog);
179ca1c9b0cSelric 	}
180ca1c9b0cSelric 
181ca1c9b0cSelric 	{
182ca1c9b0cSelric 	    char buf[81];
183ca1c9b0cSelric 	    int rv, srv;
184ca1c9b0cSelric 
185ca1c9b0cSelric 	    while ((rv = recv(s, buf, sizeof(buf), 0)) != 0 && !rk_IS_SOCKET_ERROR(rv)) {
186ca1c9b0cSelric 		buf[rv] = 0;
187ca1c9b0cSelric 		fprintf(stderr, "[%s] Received [%s]\n", prog, buf);
188ca1c9b0cSelric 
189ca1c9b0cSelric 		/* simple echo */
190ca1c9b0cSelric 		srv = send(s, buf, rv, 0);
191ca1c9b0cSelric 		if (srv != rv) {
192ca1c9b0cSelric 		    if (rk_IS_SOCKET_ERROR(srv))
193ca1c9b0cSelric 			fprintf(stderr, "[%s] send() error [%s]\n",
194ca1c9b0cSelric 				getprogname(), strerror(rk_SOCK_ERRNO));
195ca1c9b0cSelric 		    else
196ca1c9b0cSelric 			fprintf(stderr, "[%s] send() size mismatch %d != %d",
197ca1c9b0cSelric 				getprogname(), srv, rv);
198ca1c9b0cSelric 		}
199ca1c9b0cSelric 
200ca1c9b0cSelric 		if (!strcmp(buf, "exit")) {
201ca1c9b0cSelric 		    fprintf(stderr, "[%s] Exiting...\n", prog);
202ca1c9b0cSelric 		    shutdown(s, SD_SEND);
203ca1c9b0cSelric 		    rk_closesocket(s);
204ca1c9b0cSelric 		    return 0;
205ca1c9b0cSelric 		}
206ca1c9b0cSelric 	    }
207ca1c9b0cSelric 
208ca1c9b0cSelric 	    fprintf(stderr, "[%s] recv() failed (%s)\n",
209ca1c9b0cSelric 		    getprogname(),
210ca1c9b0cSelric 		    strerror(rk_SOCK_ERRNO));
211ca1c9b0cSelric 	}
212ca1c9b0cSelric 
213ca1c9b0cSelric 	rk_closesocket(s);
214ca1c9b0cSelric     }
215ca1c9b0cSelric 
216ca1c9b0cSelric     return 1;
217ca1c9b0cSelric }
218ca1c9b0cSelric 
219ca1c9b0cSelric static int
test_simple_echo(void)220ca1c9b0cSelric test_simple_echo(void)
221ca1c9b0cSelric {
222ca1c9b0cSelric     fprintf (stderr, "[%s] Starting echo test\n", prog);
223ca1c9b0cSelric 
224ca1c9b0cSelric     if (is_client) {
225ca1c9b0cSelric 
226ca1c9b0cSelric 	return test_simple_echo_client();
227ca1c9b0cSelric 
228ca1c9b0cSelric     } else {
229ca1c9b0cSelric 
230ca1c9b0cSelric 	fprintf (stderr, "[%s] Listening for connections...\n", prog);
231ca1c9b0cSelric 	mini_inetd(htons(PORT), NULL);
232ca1c9b0cSelric 	fprintf (stderr, "[%s] Connected\n", prog);
233ca1c9b0cSelric 
234ca1c9b0cSelric 	{
235ca1c9b0cSelric 	    char buf[81];
236ca1c9b0cSelric 	    while (gets(buf)) {
237ca1c9b0cSelric 		fprintf(stderr, "[%s] Received [%s]\n", prog, buf);
238ca1c9b0cSelric 
239ca1c9b0cSelric 		if (!strcmp(buf, "exit"))
240ca1c9b0cSelric 		    return 0;
241ca1c9b0cSelric 
242ca1c9b0cSelric 		/* simple echo */
243ca1c9b0cSelric 		puts(buf);
244ca1c9b0cSelric 	    }
245ca1c9b0cSelric 
246ca1c9b0cSelric 	    fprintf(stderr, "[%s] gets() failed (%s)\n", prog, _strerror("gets"));
247ca1c9b0cSelric 	}
248ca1c9b0cSelric     }
249ca1c9b0cSelric 
250ca1c9b0cSelric     return 1;
251ca1c9b0cSelric }
252ca1c9b0cSelric 
253ca1c9b0cSelric static int
do_client(void)254ca1c9b0cSelric do_client(void)
255ca1c9b0cSelric {
256ca1c9b0cSelric     int rv = 0;
257ca1c9b0cSelric 
258ca1c9b0cSelric     rk_SOCK_INIT();
259ca1c9b0cSelric 
260ca1c9b0cSelric     prog = "Client";
261ca1c9b0cSelric     is_client = 1;
262ca1c9b0cSelric 
263ca1c9b0cSelric     fprintf(stderr, "Starting client...\n");
264ca1c9b0cSelric 
265ca1c9b0cSelric     rv = test_simple_echo_socket();
266ca1c9b0cSelric 
267ca1c9b0cSelric     rk_SOCK_EXIT();
268ca1c9b0cSelric 
269ca1c9b0cSelric     return rv;
270ca1c9b0cSelric }
271ca1c9b0cSelric 
272ca1c9b0cSelric static int
do_server(void)273ca1c9b0cSelric do_server(void)
274ca1c9b0cSelric {
275ca1c9b0cSelric     int rv = 0;
276ca1c9b0cSelric 
277ca1c9b0cSelric     rk_SOCK_INIT();
278ca1c9b0cSelric 
279ca1c9b0cSelric     prog = "Server";
280ca1c9b0cSelric 
281ca1c9b0cSelric     fprintf(stderr, "Starting server...\n");
282ca1c9b0cSelric 
283ca1c9b0cSelric     rv = test_simple_echo_socket();
284ca1c9b0cSelric 
285ca1c9b0cSelric     rk_SOCK_EXIT();
286ca1c9b0cSelric 
287ca1c9b0cSelric     return rv;
288ca1c9b0cSelric }
289ca1c9b0cSelric 
290ca1c9b0cSelric static time_t
wait_callback(void * p)291ca1c9b0cSelric wait_callback(void *p)
292ca1c9b0cSelric {
293ca1c9b0cSelric     return (time_t)-1;
294ca1c9b0cSelric }
295ca1c9b0cSelric 
296ca1c9b0cSelric static int
do_test(char * path)297ca1c9b0cSelric do_test(char * path)
298ca1c9b0cSelric {
299ca1c9b0cSelric     intptr_t p_server;
300ca1c9b0cSelric     intptr_t p_client;
301ca1c9b0cSelric     int client_rv;
302ca1c9b0cSelric     int server_rv;
303ca1c9b0cSelric 
304ca1c9b0cSelric     p_server = _spawnl(_P_NOWAIT, path, path, "--server", NULL);
305ca1c9b0cSelric     if (p_server <= 0) {
306ca1c9b0cSelric 	fprintf(stderr, "%s: %s", path, _strerror("Can't start server process"));
307ca1c9b0cSelric 	return 1;
308ca1c9b0cSelric     }
309ca1c9b0cSelric #ifdef _WIN32
310ca1c9b0cSelric     /* On Windows, the _spawn*() functions return a process handle on
311ca1c9b0cSelric        success.  We need a process ID for use with
312ca1c9b0cSelric        wait_for_process_timed(). */
313ca1c9b0cSelric 
314ca1c9b0cSelric     p_server = GetProcessId((HANDLE) p_server);
315ca1c9b0cSelric #endif
316ca1c9b0cSelric     fprintf(stderr, "Created server process ID %d\n", p_server);
317ca1c9b0cSelric 
318ca1c9b0cSelric     p_client = _spawnl(_P_NOWAIT, path, path, "--client", NULL);
319ca1c9b0cSelric     if (p_client <= 0) {
320ca1c9b0cSelric 	fprintf(stderr, "%s: %s", path, _strerror("Can't start client process"));
321ca1c9b0cSelric 	fprintf(stderr, "Waiting for server process to terminate ...");
322ca1c9b0cSelric 	wait_for_process_timed(p_server, wait_callback, NULL, 5);
323ca1c9b0cSelric 	fprintf(stderr, "DONE\n");
324ca1c9b0cSelric 	return 1;
325ca1c9b0cSelric     }
326ca1c9b0cSelric #ifdef _WIN32
327ca1c9b0cSelric     p_client = GetProcessId((HANDLE) p_client);
328ca1c9b0cSelric #endif
329ca1c9b0cSelric     fprintf(stderr, "Created client process ID %d\n", p_client);
330ca1c9b0cSelric 
331ca1c9b0cSelric     fprintf(stderr, "Waiting for client process to terminate ...");
332ca1c9b0cSelric     client_rv = wait_for_process_timed(p_client, wait_callback, NULL, 5);
333ca1c9b0cSelric     if (SE_IS_ERROR(client_rv)) {
334ca1c9b0cSelric 	fprintf(stderr, "\nwait_for_process_timed() failed for client. rv=%d\n", client_rv);
335ca1c9b0cSelric     } else {
336ca1c9b0cSelric 	fprintf(stderr, "DONE\n");
337ca1c9b0cSelric     }
338ca1c9b0cSelric 
339ca1c9b0cSelric     fprintf(stderr, "Waiting for server process to terminate ...");
340ca1c9b0cSelric     server_rv = wait_for_process_timed(p_server, wait_callback, NULL, 5);
341ca1c9b0cSelric     if (SE_IS_ERROR(server_rv)) {
342ca1c9b0cSelric 	fprintf(stderr, "\nwait_for_process_timed() failed for server. rv=%d\n", server_rv);
343ca1c9b0cSelric     } else {
344ca1c9b0cSelric 	fprintf(stderr, "DONE\n");
345ca1c9b0cSelric     }
346ca1c9b0cSelric 
347ca1c9b0cSelric     if (client_rv == 0 && server_rv == 0) {
348ca1c9b0cSelric 	fprintf(stderr, "PASS\n");
349ca1c9b0cSelric 	return 0;
350ca1c9b0cSelric     } else {
351ca1c9b0cSelric 	fprintf(stderr, "FAIL: Client rv=%d, Server rv=%d\n", client_rv, server_rv);
352ca1c9b0cSelric 	return 1;
353ca1c9b0cSelric     }
354ca1c9b0cSelric }
355ca1c9b0cSelric 
main(int argc,char ** argv)356ca1c9b0cSelric int main(int argc, char ** argv)
357ca1c9b0cSelric {
358ca1c9b0cSelric     setprogname(argv[0]);
359ca1c9b0cSelric 
360ca1c9b0cSelric     if (argc == 2 && strcmp(argv[1], "--client") == 0)
361ca1c9b0cSelric 	return do_client();
362ca1c9b0cSelric     else if (argc == 2 && strcmp(argv[1], "--server") == 0)
363ca1c9b0cSelric 	return do_server();
364ca1c9b0cSelric     else if (argc == 1)
365ca1c9b0cSelric 	return do_test(argv[0]);
366ca1c9b0cSelric     else {
367ca1c9b0cSelric 	printf ("%s: Test mini_inetd() function.  Run with no arguments to start test\n",
368ca1c9b0cSelric 		argv[0]);
369ca1c9b0cSelric 	return 1;
370ca1c9b0cSelric     }
371ca1c9b0cSelric }
372