/* * Simple DCCP v6 client 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 #define TXBUFLEN 1024 static void usage(const char *prog) { errx(1, "Usage: %s address port\n", prog); } int main(int argc, char **argv) { int cfd, ret, psize; ssize_t txlen, rxlen; unsigned int port, svc = SVC; struct in6_addr c_in6; struct sockaddr_in6 c_sin6; char txbuf[TXBUFLEN], rxbuf[RXBUFLEN]; if (argc != 3) usage(argv[0]); ret = inet_pton(AF_INET6, argv[1], &c_in6); if (ret < 0) err(1, "inet_pton"); port = atoi(argv[2]); if (port > MAX_PORT) errx(1, "invalid port number\n"); cfd = socket(AF_INET6, SOCK_DCCP, IPPROTO_DCCP); if (cfd < 0) err(1, "socket"); ret = setsockopt(cfd, SOL_DCCP, DCCP_SOCKOPT_PACKET_SIZE, &psize, sizeof(psize)); if (ret < 0) err(1, "setsockopt"); ret = setsockopt(cfd, SOL_DCCP, DCCP_SOCKOPT_SERVICE, &svc, sizeof(svc)); if (ret < 0) err(1, "setsockopt"); memset(&c_sin6, 0, sizeof(c_sin6)); c_sin6.sin6_family = AF_INET6; c_sin6.sin6_port = htons(port); memcpy(&c_sin6.sin6_addr, &c_in6, sizeof(c_in6)); ret = connect(cfd, (struct sockaddr *)&c_sin6, sizeof(c_sin6)); if (ret < 0) err(1, "connect"); printf("connected\n"); memset(txbuf, 'X', sizeof(txbuf)); txlen = send(cfd, txbuf, sizeof(txbuf), 0); if (txlen < 0) err(1, "send"); if (!txlen) errx(0, "connection closed"); if (txlen != sizeof(txbuf)) warnx("incomplete send, only %zd of %zd\n", txlen, sizeof(txbuf)); /* wait for echo */ 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); if (rxlen != txlen || memcmp(rxbuf, txbuf, rxlen)) warnx("rxbuf != txbuf"); printf("done\n"); return 0; }