summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2006-03-26 19:10:27 +0000
committerrwatson <rwatson@FreeBSD.org>2006-03-26 19:10:27 +0000
commit6e86a80ea81e31017ad9a194608dc83546aea1a4 (patch)
tree1c6eb5bef3e649fc5788627b18eee29fa0efdcc9 /tools
parent5d9ced7701c1899404b342b4eb50fafb0e49a259 (diff)
downloadFreeBSD-src-6e86a80ea81e31017ad9a194608dc83546aea1a4.zip
FreeBSD-src-6e86a80ea81e31017ad9a194608dc83546aea1a4.tar.gz
Add simple regression test to ping pong a data packet over SPX in stream
mode. Support both connection via connect() and sendto(), but don't compile in sendto() for now, since netipx doesn't appear to actually implement that (doh).
Diffstat (limited to 'tools')
-rw-r--r--tools/regression/netipx/spxloopback/Makefile12
-rw-r--r--tools/regression/netipx/spxloopback/spxloopback.c258
2 files changed, 270 insertions, 0 deletions
diff --git a/tools/regression/netipx/spxloopback/Makefile b/tools/regression/netipx/spxloopback/Makefile
new file mode 100644
index 0000000..a5a47ae
--- /dev/null
+++ b/tools/regression/netipx/spxloopback/Makefile
@@ -0,0 +1,12 @@
+#
+# $FreeBSD$
+#
+
+PROG= spxloopback
+NO_MAN=
+
+DPADD= ${LIBIPX};
+LDADD= -lipx
+WARNS= 3
+
+.include <bsd.prog.mk>
diff --git a/tools/regression/netipx/spxloopback/spxloopback.c b/tools/regression/netipx/spxloopback/spxloopback.c
new file mode 100644
index 0000000..9561cff
--- /dev/null
+++ b/tools/regression/netipx/spxloopback/spxloopback.c
@@ -0,0 +1,258 @@
+/*-
+ * Copyright (c) 2006 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$Exp $
+ */
+
+/*
+ * Simple netipx regression test that attempts to build an SPX stream socket
+ * pair, and send data twice over the stream, once in each direction.
+ * Purposefully pick a small packet length that should fit into the buffers
+ * at both ends, and therefore not result in a buffer deadlock.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netipx/ipx.h>
+
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define IPX_ENDPOINT "0xbebe.1.0x8a13"
+#define PACKETLEN 128
+
+#if 0
+#define SPX_SUPPORTS_SENDTO_WITH_CONNECT
+#endif
+
+static void
+packet_fill(u_char *packet)
+{
+ int i;
+
+ for (i = 0; i < PACKETLEN; i++)
+ packet[i] = (i & 0xff);
+}
+
+static int
+packet_check(u_char *packet)
+{
+ int i;
+
+ for (i = 0; i < PACKETLEN; i++) {
+ if (packet[i] != (i & 0xff))
+ return (-1);
+ }
+ return (0);
+}
+
+#ifdef SPX_SUPPORTS_SENDTO_WITH_CONNECT
+static void
+my_sendto(int sock, const char *who, pid_t pid, struct sockaddr *sa,
+ socklen_t sa_len)
+{
+ u_char packet[PACKETLEN];
+ ssize_t len;
+ int error;
+
+ packet_fill(packet);
+ len = sendto(sock, packet, sizeof(packet), 0, sa, sa_len);
+ if (len < 0) {
+ error = errno;
+ (void)kill(pid, SIGTERM);
+ errno = error;
+ err(-1, "%s: sendto()", who);
+ }
+ if (len != sizeof(packet)) {
+ (void)kill(pid, SIGTERM);
+ errx(-1, "%s: sendto(): short send (%d length, %d sent)",
+ who, sizeof(packet), len);
+ }
+}
+#endif
+
+static void
+my_send(int sock, const char *who, pid_t pid)
+{
+ u_char packet[PACKETLEN];
+ ssize_t len;
+ int error;
+
+ packet_fill(packet);
+ len = send(sock, packet, sizeof(packet), 0);
+ if (len < 0) {
+ error = errno;
+ (void)kill(pid, SIGTERM);
+ errno = error;
+ err(-1, "%s: send()", who);
+ }
+ if (len != sizeof(packet)) {
+ (void)kill(pid, SIGTERM);
+ errx(-1, "%s: send(): short send (%d length, %d sent)", who,
+ sizeof(packet), len);
+ }
+}
+
+static void
+my_recv(int sock, const char *who, pid_t pid)
+{
+ u_char packet[PACKETLEN];
+ ssize_t len;
+ int error;
+
+ bzero(packet, sizeof(packet));
+ len = recv(sock, packet, sizeof(packet), 0);
+ if (len < 0) {
+ errno = error;
+ (void)kill(pid, SIGTERM);
+ errno = error;
+ err(-1, "%s: recv()", who);
+ }
+ if (len != sizeof(packet)) {
+ (void)kill(pid, SIGTERM);
+ errx(-1, "%s: recv(): got %d expected %d", who, len,
+ sizeof(packet));
+ }
+ if (packet_check(packet) < 0) {
+ (void)kill(pid, SIGTERM);
+ errx(-1, "%s: recv(): got bad data", who);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int error, sock_listen, sock_recv, sock_send;
+ struct sockaddr_ipx sipx_listen, sipx_send;
+ pid_t childpid, parentpid;
+
+ /*
+ * Socket to receive with.
+ */
+ sock_listen = socket(PF_IPX, SOCK_STREAM, 0);
+ if (sock_listen < 0)
+ err(-1, "sock_listen = socket(PF_IPX, SOCK_STREAM, 0)");
+
+ bzero(&sipx_listen, sizeof(sipx_listen));
+ sipx_listen.sipx_len = sizeof(sipx_listen);
+ sipx_listen.sipx_family = AF_IPX;
+ sipx_listen.sipx_addr = ipx_addr(IPX_ENDPOINT);
+
+ if (bind(sock_listen, (struct sockaddr *)&sipx_listen,
+ sizeof(sipx_listen)) < 0)
+ err(-1, "bind(sock_listen)");
+
+ if (listen(sock_listen, -1) < 0)
+ err(-1, "listen(sock_listen)");
+
+ parentpid = getpid();
+
+ childpid = fork();
+ if (childpid < 0)
+ err(-1, "fork()");
+
+ if (childpid == 0) {
+ /*
+ * The child: accept connections and process data on them.
+ */
+ while (1) {
+ sock_recv = accept(sock_listen, NULL, NULL);
+ if (sock_recv < 0) {
+ warn("accept()");
+ continue;
+ }
+
+ my_recv(sock_recv, "listener", parentpid);
+ my_send(sock_recv, "listener", parentpid);
+
+ close(sock_recv);
+ }
+ } else {
+ /*
+ * The parent: connect, send data, receive it back, and exit;
+ * build two connections, once using a full connect() API
+ * call, and the second using sendto().
+ */
+
+ /*
+ * Socket to send with.
+ */
+ sock_send = socket(PF_IPX, SOCK_STREAM, 0);
+ if (sock_send < 0) {
+ error = errno;
+ (void)kill(childpid, SIGTERM);
+ errno = error;
+ err(-1, "sock_send = socket(PF_IPX, SOCK_STREAM, 0)");
+ }
+
+ bzero(&sipx_send, sizeof(sipx_send));
+ sipx_send.sipx_len = sizeof(sipx_send);
+ sipx_send.sipx_family = AF_IPX;
+ sipx_send.sipx_addr = ipx_addr(IPX_ENDPOINT);
+
+ if (connect(sock_send, (struct sockaddr *)&sipx_send,
+ sizeof(sipx_send)) < 0) {
+ error = errno;
+ (void)kill(childpid, SIGTERM);
+ errno = error;
+ err(-1, "sock_send = socket(PF_IPX, SOCK_STREAM, 0)");
+ }
+
+ my_send(sock_send, "connector", childpid);
+ my_recv(sock_send, "connector", childpid);
+
+ close(sock_send);
+
+#ifdef SPX_SUPPORTS_SENDTO_WITH_CONNECT
+ sock_send = socket(PF_IPX, SOCK_STREAM, 0);
+ if (sock_send < 0) {
+ error = errno;
+ (void)kill(childpid, SIGTERM);
+ errno = error;
+ err(-1, "sock_send = socket(PF_IPX, SOCK_STREAM, 0)");
+ }
+
+ bzero(&sipx_send, sizeof(sipx_send));
+ sipx_send.sipx_len = sizeof(sipx_send);
+ sipx_send.sipx_family = AF_IPX;
+ sipx_send.sipx_addr = ipx_addr(IPX_ENDPOINT);
+
+ my_sendto(sock_send, "connector", childpid,
+ (struct sockaddr *)&sipx_send, sizeof(sipx_send));
+ my_recv(sock_send, "connector", childpid);
+
+ close(sock_send);
+#endif
+
+ (void)kill(childpid, SIGTERM);
+ }
+
+ return (0);
+}
OpenPOWER on IntegriCloud