From ffd446110e23e0d9f47e0f5328b9104f4f0722e0 Mon Sep 17 00:00:00 2001 From: Robert Watson Date: Sat, 17 Jul 2004 17:12:15 +0000 Subject: [PATCH] Add a simple tool to bind netatalk sockets and perform send operations. This isn't a classic regression test in that it doesn't have a notion of pass fail, it's more of an exercise tool. It attempts to exercise unbound, bound, unconnected, and connected variations on SOCK_DGRAM sockets. --- .../regression/netatalk/simple_send/Makefile | 8 + .../netatalk/simple_send/simple_send.c | 162 ++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 tools/regression/netatalk/simple_send/Makefile create mode 100644 tools/regression/netatalk/simple_send/simple_send.c diff --git a/tools/regression/netatalk/simple_send/Makefile b/tools/regression/netatalk/simple_send/Makefile new file mode 100644 index 000000000000..54e486f4c10d --- /dev/null +++ b/tools/regression/netatalk/simple_send/Makefile @@ -0,0 +1,8 @@ +# +# $FreeBSD$ +# + +PROG= simple_send +NOMAN= yes + +.include diff --git a/tools/regression/netatalk/simple_send/simple_send.c b/tools/regression/netatalk/simple_send/simple_send.c new file mode 100644 index 000000000000..e2e5740aef54 --- /dev/null +++ b/tools/regression/netatalk/simple_send/simple_send.c @@ -0,0 +1,162 @@ +/*- + * Copyright (c) 2004 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$ + */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* + * This is a simple test tool to bind netatalk SOCK_DGRAM sockets and perform + * simple send operations that exercise each combination of bound and + * connected endpoints, with the intent of exercising the various kernel send + * case. + * + * In order to run this test, configure NETATALK into the kernel. Use + * ifconfig to set an appletalk address on an interface. Run this tool with + * two arguments: a local address and port number, and a remote address and + * port number. + * + * It is recommended that you try running it with some interesting address + * and port thresholds, including ATADDR_ANYNET, ATADDR_ANYNODE, + * ATADDR_ANYPORT, and ATADDR_ANYBCAST. Try both remote unicast addresses + * and the local address, which will help to test local delivery (although + * not socket receive). + */ + +/* + * Create a netatalk socket with specified source and destination, if + * desired. If a source is specified, bind it. If a destination is + * specified, connect it. + */ +static int +socket_between(struct sockaddr_at *from, struct sockaddr_at *to) +{ + int s; + + s = socket(PF_APPLETALK, SOCK_DGRAM, 0); + if (s == -1) + errx(1, "socket: %s\n", strerror(errno)); + + if (from != NULL) { + if (bind(s, (struct sockaddr *)from, sizeof(*from)) != 0) + errx(1, "bind: %u.%u returned %s\n", + ntohs(from->sat_addr.s_net), from->sat_addr.s_node, + strerror(errno)); + } + + if (to != NULL) { + if (connect(s, (struct sockaddr *)to, sizeof(*to)) != 0) + errx(1, "connect: %u.%u returned %s\n", + ntohs(to->sat_addr.s_net), to->sat_addr.s_node, + strerror(errno)); + } + return (s); +} + +int +main(int argc, char *argv[]) +{ + struct sockaddr_at sat_from, sat_to; + char *addr_from, *addr_to; + u_int net, node, port; + char msg[] = "TEST"; + ssize_t len; + int s; + + if (argc != 3) + errx(1, "simple_send from_addr to_addr"); + + addr_from = argv[1]; + sat_from.sat_family = AF_APPLETALK; + sat_from.sat_len = sizeof(sat_from); + if (sscanf(addr_from, "%u.%u:%u", &net, &node, &port) != 3 || + net > 0xfff || node > 0xfe) + errx(1, "%s: illegal address", addr_from); + sat_from.sat_addr.s_net = htons(net); + sat_from.sat_addr.s_node = node; + sat_from.sat_port = port; + + addr_to = argv[2]; + sat_to.sat_family = AF_APPLETALK; + sat_to.sat_len = sizeof(sat_to); + if (sscanf(addr_to, "%u.%u:%u", &net, &node, &port) != 3 || + net > 0xffff || node > 0xfe) + errx(1, "%s: illegal address", addr_to); + sat_to.sat_addr.s_net = htons(net); + sat_to.sat_addr.s_node = node; + sat_from.sat_port = port; + + printf("Address source is %u.%u:%u, address destination is %u.%u:%u\n", + ntohs(sat_from.sat_addr.s_net), sat_from.sat_addr.s_node, + sat_from.sat_port, + ntohs(sat_to.sat_addr.s_net), sat_to.sat_addr.s_net, + sat_to.sat_port); + + /* + * First, create a socket and use explicit sendto() to specify + * destination. + */ + s = socket_between(NULL, NULL); + len = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sat_to, + sizeof(sat_to)); + close(s); + + /* + * Next, specify the destination for a connect() but not the source. + */ + s = socket_between(NULL, &sat_to); + len = send(s, msg, sizeof(msg), 0); + close(s); + + /* + * Now, bind the source, but not connect the destination. + */ + s = socket_between(&sat_from, NULL); + len = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sat_to, + sizeof(sat_to)); + close(s); + + /* + * Finally, bind and connect. + */ + s = socket_between(&sat_from, &sat_to); + len = send(s, msg, sizeof(msg), 0); + close(s); + + exit(0); +}