/* * Simple DCCP v6 server test code. * * Copyright (c) 2006 James Morris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include "local.h" #define RXBUFLEN 1024 static void usage(const char *prog) { errx(1, "Usage: %s port\n", prog); } int main(int argc, char **argv) { char peer[INET6_ADDRSTRLEN], rxbuf[RXBUFLEN]; int pfd, cfd, ret, psize = RXBUFLEN; unsigned int port, svc = SVC; ssize_t rxlen, txlen; socklen_t socklen; struct sockaddr_in6 s_sin6, c_sin6; if (argc != 2) usage(argv[0]); port = atoi(argv[1]); if (port > MAX_PORT) errx(1, "invalid port number\n"); pfd = socket(AF_INET6, SOCK_DCCP, IPPROTO_DCCP); if (pfd < 0) err(1, "socket"); ret = setsockopt(pfd, SOL_DCCP, DCCP_SOCKOPT_PACKET_SIZE, &psize, sizeof(psize)); if (ret < 0) err(1, "setsockopt"); ret = setsockopt(pfd, SOL_DCCP, DCCP_SOCKOPT_SERVICE, &svc, sizeof(svc)); if (ret < 0) err(1, "setsockopt"); memset(&s_sin6, 0, sizeof(s_sin6)); s_sin6.sin6_family = AF_INET6; s_sin6.sin6_port = htons(port); ret = bind(pfd, (struct sockaddr *)&s_sin6, sizeof(s_sin6)); if (ret < 0) err(1, "bind"); ret = listen(pfd, 5); if (ret < 0) err(1, "listen"); /* Worst API ever */ memset(&c_sin6, 0, sizeof(c_sin6)); socklen = sizeof (c_sin6); cfd = accept(pfd, (struct sockaddr *)&c_sin6, &socklen); if (cfd < 0) err(1, "accept"); if (!inet_ntop(AF_INET6, &c_sin6.sin6_addr, peer, INET6_ADDRSTRLEN)) err(1, "inet_ntop"); printf("connection from %s:[%d]\n", peer, ntohs(c_sin6.sin6_port)); memset(&rxbuf, 0, sizeof(rxbuf)); rxlen = recv(cfd, rxbuf, sizeof(rxbuf), 0); if (rxlen < 0) err(1, "recv"); if (!rxlen) errx(0, "connection closed"); printf("RX %zd bytes: %s\n", rxlen, rxbuf); /* just echo it back */ txlen = send(cfd, rxbuf, rxlen, 0); if (txlen < 0) err(1, "send"); if (txlen != rxlen) warnx("incomplete send, only %zd of %zd\n", txlen, rxlen); printf("done\n"); return 0; }