1*d80889b6Sbluhm /* $OpenBSD: server-tcp.c,v 1.1 2020/01/16 21:11:17 bluhm Exp $ */ 2*d80889b6Sbluhm 3*d80889b6Sbluhm /* 4*d80889b6Sbluhm * Copyright (c) 2020 Alexander Bluhm <bluhm@openbsd.org> 5*d80889b6Sbluhm * 6*d80889b6Sbluhm * Permission to use, copy, modify, and distribute this software for any 7*d80889b6Sbluhm * purpose with or without fee is hereby granted, provided that the above 8*d80889b6Sbluhm * copyright notice and this permission notice appear in all copies. 9*d80889b6Sbluhm * 10*d80889b6Sbluhm * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*d80889b6Sbluhm * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*d80889b6Sbluhm * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*d80889b6Sbluhm * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*d80889b6Sbluhm * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*d80889b6Sbluhm * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*d80889b6Sbluhm * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*d80889b6Sbluhm */ 18*d80889b6Sbluhm 19*d80889b6Sbluhm #include <sys/types.h> 20*d80889b6Sbluhm #include <sys/socket.h> 21*d80889b6Sbluhm 22*d80889b6Sbluhm #include <err.h> 23*d80889b6Sbluhm #include <errno.h> 24*d80889b6Sbluhm #include <netdb.h> 25*d80889b6Sbluhm #include <stdio.h> 26*d80889b6Sbluhm #include <stdlib.h> 27*d80889b6Sbluhm #include <string.h> 28*d80889b6Sbluhm #include <unistd.h> 29*d80889b6Sbluhm 30*d80889b6Sbluhm #include "util.h" 31*d80889b6Sbluhm 32*d80889b6Sbluhm void __dead usage(void); 33*d80889b6Sbluhm int listen_socket(const char *, const char *); 34*d80889b6Sbluhm int accept_socket(int); 35*d80889b6Sbluhm 36*d80889b6Sbluhm void __dead 37*d80889b6Sbluhm usage(void) 38*d80889b6Sbluhm { 39*d80889b6Sbluhm fprintf(stderr, "server-tcp [-r rcvmsg] [-s sndmsg] host port\n" 40*d80889b6Sbluhm " -r rcvmsg receive from client and check message\n" 41*d80889b6Sbluhm " -s sndmsg send message to client\n"); 42*d80889b6Sbluhm exit(2); 43*d80889b6Sbluhm } 44*d80889b6Sbluhm 45*d80889b6Sbluhm int 46*d80889b6Sbluhm main(int argc, char *argv[]) 47*d80889b6Sbluhm { 48*d80889b6Sbluhm const char *host, *port; 49*d80889b6Sbluhm const char *rcvmsg = NULL, *sndmsg = NULL; 50*d80889b6Sbluhm int ch, s; 51*d80889b6Sbluhm 52*d80889b6Sbluhm while ((ch = getopt(argc, argv, "r:s:")) != -1) { 53*d80889b6Sbluhm switch (ch) { 54*d80889b6Sbluhm case 'r': 55*d80889b6Sbluhm rcvmsg = optarg; 56*d80889b6Sbluhm break; 57*d80889b6Sbluhm case 's': 58*d80889b6Sbluhm sndmsg = optarg; 59*d80889b6Sbluhm break; 60*d80889b6Sbluhm default: 61*d80889b6Sbluhm usage(); 62*d80889b6Sbluhm } 63*d80889b6Sbluhm } 64*d80889b6Sbluhm argc -= optind; 65*d80889b6Sbluhm argv += optind; 66*d80889b6Sbluhm 67*d80889b6Sbluhm if (argc == 2) { 68*d80889b6Sbluhm host = argv[0]; 69*d80889b6Sbluhm port = argv[1]; 70*d80889b6Sbluhm } else { 71*d80889b6Sbluhm usage(); 72*d80889b6Sbluhm } 73*d80889b6Sbluhm 74*d80889b6Sbluhm alarm_timeout(); 75*d80889b6Sbluhm s = listen_socket(host, port); 76*d80889b6Sbluhm print_sockname(s); 77*d80889b6Sbluhm 78*d80889b6Sbluhm switch (fork()) { 79*d80889b6Sbluhm case -1: 80*d80889b6Sbluhm err(1, "fork"); 81*d80889b6Sbluhm case 0: 82*d80889b6Sbluhm /* child continues */ 83*d80889b6Sbluhm break; 84*d80889b6Sbluhm default: 85*d80889b6Sbluhm /* parent exits and test runs in parallel */ 86*d80889b6Sbluhm _exit(0); 87*d80889b6Sbluhm } 88*d80889b6Sbluhm 89*d80889b6Sbluhm s = accept_socket(s); 90*d80889b6Sbluhm if (sndmsg != NULL) 91*d80889b6Sbluhm send_line(s, sndmsg); 92*d80889b6Sbluhm if (rcvmsg != NULL) 93*d80889b6Sbluhm receive_line(s, rcvmsg); 94*d80889b6Sbluhm 95*d80889b6Sbluhm if (close(s) == -1) 96*d80889b6Sbluhm err(1, "close"); 97*d80889b6Sbluhm 98*d80889b6Sbluhm return 0; 99*d80889b6Sbluhm } 100*d80889b6Sbluhm 101*d80889b6Sbluhm int 102*d80889b6Sbluhm listen_socket(const char *host, const char *port) 103*d80889b6Sbluhm { 104*d80889b6Sbluhm struct addrinfo hints, *res, *res0; 105*d80889b6Sbluhm int error; 106*d80889b6Sbluhm int save_errno; 107*d80889b6Sbluhm int s; 108*d80889b6Sbluhm const char *cause = NULL; 109*d80889b6Sbluhm 110*d80889b6Sbluhm memset(&hints, 0, sizeof(hints)); 111*d80889b6Sbluhm hints.ai_family = AF_UNSPEC; 112*d80889b6Sbluhm hints.ai_socktype = SOCK_STREAM; 113*d80889b6Sbluhm hints.ai_flags = AI_PASSIVE; 114*d80889b6Sbluhm error = getaddrinfo(host, port, &hints, &res0); 115*d80889b6Sbluhm if (error) 116*d80889b6Sbluhm errx(1, "%s", gai_strerror(error)); 117*d80889b6Sbluhm for (res = res0; res; res = res->ai_next) { 118*d80889b6Sbluhm s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 119*d80889b6Sbluhm if (s == -1) { 120*d80889b6Sbluhm cause = "socket"; 121*d80889b6Sbluhm continue; 122*d80889b6Sbluhm } 123*d80889b6Sbluhm if (bind(s, res->ai_addr, res->ai_addrlen) == -1) { 124*d80889b6Sbluhm cause = "bind"; 125*d80889b6Sbluhm save_errno = errno; 126*d80889b6Sbluhm close(s); 127*d80889b6Sbluhm errno = save_errno; 128*d80889b6Sbluhm continue; 129*d80889b6Sbluhm } 130*d80889b6Sbluhm break; /* okay we got one */ 131*d80889b6Sbluhm } 132*d80889b6Sbluhm if (s == -1) 133*d80889b6Sbluhm err(1, "%s", cause); 134*d80889b6Sbluhm freeaddrinfo(res0); 135*d80889b6Sbluhm 136*d80889b6Sbluhm if (listen(s, 5) == -1) 137*d80889b6Sbluhm err(1, "listen"); 138*d80889b6Sbluhm return s; 139*d80889b6Sbluhm } 140*d80889b6Sbluhm 141*d80889b6Sbluhm int 142*d80889b6Sbluhm accept_socket(int s) 143*d80889b6Sbluhm { 144*d80889b6Sbluhm struct sockaddr_storage ss; 145*d80889b6Sbluhm socklen_t slen; 146*d80889b6Sbluhm char host[NI_MAXHOST], port[NI_MAXSERV]; 147*d80889b6Sbluhm 148*d80889b6Sbluhm slen = sizeof(ss); 149*d80889b6Sbluhm s = accept(s, (struct sockaddr *)&ss, &slen); 150*d80889b6Sbluhm if (s == -1) 151*d80889b6Sbluhm err(1, "accept"); 152*d80889b6Sbluhm if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host, sizeof(host), 153*d80889b6Sbluhm port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV)) 154*d80889b6Sbluhm errx(1, "getnameinfo"); 155*d80889b6Sbluhm fprintf(stderr, "peer: %s %s\n", host, port); 156*d80889b6Sbluhm 157*d80889b6Sbluhm return s; 158*d80889b6Sbluhm } 159