#include #include #include #include #include #include #include #include #include static const int backlog = 10; static void handle_client(int fd); int main(int argc, char **argv) { struct addrinfo *ai; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE}; int res, fd; if (argc != 2) errx(1, "usage: %s port", argv[0]); res = getaddrinfo(NULL, argv[1], &hints, &ai); if (res) errx(EXIT_FAILURE, "getaddrinfo: %s", gai_strerror(res)); fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (fd < 0) err(EXIT_FAILURE, "socket"); res = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &res, sizeof(res))) err(EXIT_FAILURE, "setsockopt"); if (bind(fd, ai->ai_addr, ai->ai_addrlen)) err(EXIT_FAILURE, "bind"); if (listen(fd, backlog)) err(EXIT_FAILURE, "listen"); for (;;) { struct sockaddr_storage clt_addr; socklen_t clt_addrlen = sizeof(clt_addr); char clt_dns[NI_MAXHOST], clt_ip[NI_MAXHOST], clt_port[NI_MAXSERV]; struct sockaddr_storage srv_addr; socklen_t srv_addrlen = sizeof(srv_addr); char srv_dns[NI_MAXHOST], srv_ip[NI_MAXHOST], srv_port[NI_MAXSERV]; int newfd; /* accept(fd, NULL, NULL) */ newfd = accept(fd, (struct sockaddr *)&clt_addr, &clt_addrlen); if (newfd < 0) err(EXIT_FAILURE, "accept"); getnameinfo((struct sockaddr *)&clt_addr, clt_addrlen, clt_dns, sizeof(clt_dns), NULL, 0, 0); getnameinfo((struct sockaddr *)&clt_addr, clt_addrlen, clt_ip, sizeof(clt_ip), clt_port, sizeof(clt_port), NI_NUMERICHOST | NI_NUMERICSERV); fprintf(stderr, "client: %s (%s), port %s \n", clt_dns, clt_ip, clt_port); getsockname(newfd, (struct sockaddr *)&srv_addr, &srv_addrlen); getnameinfo((struct sockaddr *)&srv_addr, srv_addrlen, srv_dns, sizeof(srv_dns), NULL, 0, 0); getnameinfo((struct sockaddr *)&srv_addr, srv_addrlen, srv_ip, sizeof(srv_ip), srv_port, sizeof(srv_port), NI_NUMERICHOST | NI_NUMERICSERV); fprintf(stderr, "server: %s (%s), port %s \n", srv_dns, srv_ip, srv_port); handle_client(newfd); fprintf(stderr, "close connection\n"); close(newfd); } close(fd); freeaddrinfo(ai); } static void handle_client(int fd) { char buf[64]; for (;;) { size_t count = read(fd, buf, sizeof(buf)), offset = 0; if (count < 0) { if (errno == EAGAIN || errno == EINTR) continue; err(EXIT_FAILURE, "read"); } if (count == 0) break; while (offset < count) { ssize_t res = write(fd, buf + offset, count - offset); if (res < 0) { if (errno == EAGAIN || errno == EINTR) continue; err(EXIT_FAILURE, "write"); } offset += res; } } }