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