simple_send.c revision 132304
1132302Srwatson/*- 2132302Srwatson * Copyright (c) 2004 Robert N. M. Watson 3132302Srwatson * All rights reserved. 4132302Srwatson * 5132302Srwatson * Redistribution and use in source and binary forms, with or without 6132302Srwatson * modification, are permitted provided that the following conditions 7132302Srwatson * are met: 8132302Srwatson * 1. Redistributions of source code must retain the above copyright 9132302Srwatson * notice, this list of conditions and the following disclaimer. 10132302Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11132302Srwatson * notice, this list of conditions and the following disclaimer in the 12132302Srwatson * documentation and/or other materials provided with the distribution. 13132302Srwatson * 14132302Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132302Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132302Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132302Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132302Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19132302Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20132302Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132302Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22132302Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23132302Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24132302Srwatson * SUCH DAMAGE. 25132302Srwatson * 26132302Srwatson * $FreeBSD: head/tools/regression/netatalk/simple_send/simple_send.c 132304 2004-07-17 17:16:16Z rwatson $ 27132302Srwatson */ 28132302Srwatson 29132302Srwatson#include <sys/types.h> 30132302Srwatson#include <sys/socket.h> 31132302Srwatson 32132302Srwatson#include <arpa/inet.h> 33132302Srwatson 34132302Srwatson#include <netatalk/at.h> 35132302Srwatson 36132302Srwatson#include <err.h> 37132302Srwatson#include <errno.h> 38132302Srwatson#include <stdio.h> 39132302Srwatson#include <stdlib.h> 40132302Srwatson#include <string.h> 41132302Srwatson#include <unistd.h> 42132302Srwatson 43132302Srwatson/* 44132302Srwatson * This is a simple test tool to bind netatalk SOCK_DGRAM sockets and perform 45132302Srwatson * simple send operations that exercise each combination of bound and 46132302Srwatson * connected endpoints, with the intent of exercising the various kernel send 47132302Srwatson * case. 48132302Srwatson * 49132302Srwatson * In order to run this test, configure NETATALK into the kernel. Use 50132302Srwatson * ifconfig to set an appletalk address on an interface. Run this tool with 51132302Srwatson * two arguments: a local address and port number, and a remote address and 52132302Srwatson * port number. 53132302Srwatson * 54132302Srwatson * It is recommended that you try running it with some interesting address 55132302Srwatson * and port thresholds, including ATADDR_ANYNET, ATADDR_ANYNODE, 56132302Srwatson * ATADDR_ANYPORT, and ATADDR_ANYBCAST. Try both remote unicast addresses 57132302Srwatson * and the local address, which will help to test local delivery (although 58132302Srwatson * not socket receive). 59132302Srwatson */ 60132302Srwatson 61132302Srwatson/* 62132302Srwatson * Create a netatalk socket with specified source and destination, if 63132302Srwatson * desired. If a source is specified, bind it. If a destination is 64132302Srwatson * specified, connect it. 65132302Srwatson */ 66132302Srwatsonstatic int 67132302Srwatsonsocket_between(struct sockaddr_at *from, struct sockaddr_at *to) 68132302Srwatson{ 69132302Srwatson int s; 70132302Srwatson 71132304Srwatson s = socket(PF_APPLETALK, SOCK_DGRAM, ATPROTO_DDP); 72132302Srwatson if (s == -1) 73132302Srwatson errx(1, "socket: %s\n", strerror(errno)); 74132302Srwatson 75132302Srwatson if (from != NULL) { 76132302Srwatson if (bind(s, (struct sockaddr *)from, sizeof(*from)) != 0) 77132302Srwatson errx(1, "bind: %u.%u returned %s\n", 78132302Srwatson ntohs(from->sat_addr.s_net), from->sat_addr.s_node, 79132302Srwatson strerror(errno)); 80132302Srwatson } 81132302Srwatson 82132302Srwatson if (to != NULL) { 83132302Srwatson if (connect(s, (struct sockaddr *)to, sizeof(*to)) != 0) 84132302Srwatson errx(1, "connect: %u.%u returned %s\n", 85132302Srwatson ntohs(to->sat_addr.s_net), to->sat_addr.s_node, 86132302Srwatson strerror(errno)); 87132302Srwatson } 88132302Srwatson return (s); 89132302Srwatson} 90132302Srwatson 91132302Srwatsonint 92132302Srwatsonmain(int argc, char *argv[]) 93132302Srwatson{ 94132302Srwatson struct sockaddr_at sat_from, sat_to; 95132302Srwatson char *addr_from, *addr_to; 96132302Srwatson u_int net, node, port; 97132302Srwatson char msg[] = "TEST"; 98132302Srwatson ssize_t len; 99132302Srwatson int s; 100132302Srwatson 101132302Srwatson if (argc != 3) 102132302Srwatson errx(1, "simple_send from_addr to_addr"); 103132302Srwatson 104132302Srwatson addr_from = argv[1]; 105132302Srwatson sat_from.sat_family = AF_APPLETALK; 106132302Srwatson sat_from.sat_len = sizeof(sat_from); 107132302Srwatson if (sscanf(addr_from, "%u.%u:%u", &net, &node, &port) != 3 || 108132302Srwatson net > 0xfff || node > 0xfe) 109132302Srwatson errx(1, "%s: illegal address", addr_from); 110132302Srwatson sat_from.sat_addr.s_net = htons(net); 111132302Srwatson sat_from.sat_addr.s_node = node; 112132302Srwatson sat_from.sat_port = port; 113132302Srwatson 114132302Srwatson addr_to = argv[2]; 115132302Srwatson sat_to.sat_family = AF_APPLETALK; 116132302Srwatson sat_to.sat_len = sizeof(sat_to); 117132302Srwatson if (sscanf(addr_to, "%u.%u:%u", &net, &node, &port) != 3 || 118132302Srwatson net > 0xffff || node > 0xfe) 119132302Srwatson errx(1, "%s: illegal address", addr_to); 120132302Srwatson sat_to.sat_addr.s_net = htons(net); 121132302Srwatson sat_to.sat_addr.s_node = node; 122132302Srwatson sat_from.sat_port = port; 123132302Srwatson 124132302Srwatson printf("Address source is %u.%u:%u, address destination is %u.%u:%u\n", 125132302Srwatson ntohs(sat_from.sat_addr.s_net), sat_from.sat_addr.s_node, 126132302Srwatson sat_from.sat_port, 127132302Srwatson ntohs(sat_to.sat_addr.s_net), sat_to.sat_addr.s_net, 128132302Srwatson sat_to.sat_port); 129132302Srwatson 130132302Srwatson /* 131132302Srwatson * First, create a socket and use explicit sendto() to specify 132132302Srwatson * destination. 133132302Srwatson */ 134132302Srwatson s = socket_between(NULL, NULL); 135132302Srwatson len = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sat_to, 136132302Srwatson sizeof(sat_to)); 137132302Srwatson close(s); 138132302Srwatson 139132302Srwatson /* 140132302Srwatson * Next, specify the destination for a connect() but not the source. 141132302Srwatson */ 142132302Srwatson s = socket_between(NULL, &sat_to); 143132302Srwatson len = send(s, msg, sizeof(msg), 0); 144132302Srwatson close(s); 145132302Srwatson 146132302Srwatson /* 147132302Srwatson * Now, bind the source, but not connect the destination. 148132302Srwatson */ 149132302Srwatson s = socket_between(&sat_from, NULL); 150132302Srwatson len = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sat_to, 151132302Srwatson sizeof(sat_to)); 152132302Srwatson close(s); 153132302Srwatson 154132302Srwatson /* 155132302Srwatson * Finally, bind and connect. 156132302Srwatson */ 157132302Srwatson s = socket_between(&sat_from, &sat_to); 158132302Srwatson len = send(s, msg, sizeof(msg), 0); 159132302Srwatson close(s); 160132302Srwatson 161132302Srwatson exit(0); 162132302Srwatson} 163