1263445Sasomers/* 2263445Sasomers * Copyright (c) 2014 Spectra Logic Corporation 3263445Sasomers * All rights reserved. 4265586Sasomers * 5263445Sasomers * Redistribution and use in source and binary forms, with or without 6263445Sasomers * modification, are permitted provided that the following conditions 7263445Sasomers * are met: 8263445Sasomers * 1. Redistributions of source code must retain the above copyright 9263445Sasomers * notice, this list of conditions, and the following disclaimer, 10263445Sasomers * without modification. 11263445Sasomers * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12263445Sasomers * substantially similar to the "NO WARRANTY" disclaimer below 13263445Sasomers * ("Disclaimer") and any redistribution must be conditioned upon 14263445Sasomers * including a substantially similar Disclaimer requirement for further 15263445Sasomers * binary redistribution. 16265586Sasomers * 17263445Sasomers * NO WARRANTY 18263445Sasomers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19263445Sasomers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20263445Sasomers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21263445Sasomers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22263445Sasomers * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23263445Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24263445Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25263445Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26263445Sasomers * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27263445Sasomers * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28263445Sasomers * POSSIBILITY OF SUCH DAMAGES. 29265586Sasomers * 30263445Sasomers * Authors: Alan Somers (Spectra Logic Corporation) 31263445Sasomers * 32263445Sasomers * $FreeBSD$ 33263445Sasomers */ 34263445Sasomers 35263445Sasomers#include <arpa/inet.h> 36263445Sasomers#include <netinet/in.h> 37263445Sasomers#include <sys/types.h> 38263445Sasomers#include <sys/socket.h> 39263445Sasomers 40263445Sasomers#include <err.h> 41263445Sasomers#include <errno.h> 42267186Sasomers#include <fcntl.h> 43263445Sasomers#include <stdio.h> 44263445Sasomers#include <stdlib.h> 45263445Sasomers#include <string.h> 46267186Sasomers#include <unistd.h> 47263445Sasomers 48265586Sasomers/* 49263445Sasomers * Sends a single UDP packet to the provided address, with SO_DONTROUTE set 50263445Sasomers * I couldn't find a way to do this with builtin utilities like nc(1) 51263445Sasomers */ 52265586Sasomersint 53265586Sasomersmain(int argc, char **argv) 54263445Sasomers{ 55263445Sasomers struct sockaddr_in dst; 56267186Sasomers int s, t; 57263445Sasomers int opt; 58263445Sasomers int ret; 59267186Sasomers ssize_t len; 60267186Sasomers const char* sendbuf = "Hello, World!"; 61267186Sasomers const size_t buflen = 80; 62267186Sasomers char recvbuf[buflen]; 63263445Sasomers 64267186Sasomers if (argc != 3) { 65267186Sasomers fprintf(stderr, "Usage: %s ip_address tapdev\n", argv[0]); 66263445Sasomers exit(2); 67263445Sasomers } 68267186Sasomers 69267186Sasomers t = open(argv[2], O_RDWR | O_NONBLOCK); 70267186Sasomers if (t < 0) 71267186Sasomers err(EXIT_FAILURE, "open"); 72267186Sasomers 73263445Sasomers s = socket(PF_INET, SOCK_DGRAM, 0); 74263445Sasomers if (s < 0) 75267186Sasomers err(EXIT_FAILURE, "socket"); 76263445Sasomers opt = 1; 77263445Sasomers 78263445Sasomers ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt)); 79263445Sasomers if (ret == -1) 80267186Sasomers err(EXIT_FAILURE, "setsockopt(SO_DONTROUTE)"); 81263445Sasomers 82263445Sasomers dst.sin_len = sizeof(dst); 83263445Sasomers dst.sin_family = AF_INET; 84263445Sasomers dst.sin_port = htons(46120); 85263445Sasomers dst.sin_addr.s_addr = inet_addr(argv[1]); 86263445Sasomers if (dst.sin_addr.s_addr == htonl(INADDR_NONE)) { 87263445Sasomers fprintf(stderr, "Invalid address: %s\n", argv[1]); 88263445Sasomers exit(2); 89263445Sasomers } 90267186Sasomers ret = sendto(s, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&dst, 91263445Sasomers dst.sin_len); 92263445Sasomers if (ret == -1) 93267186Sasomers err(EXIT_FAILURE, "sendto"); 94265586Sasomers 95267186Sasomers /* Verify that the packet went to the desired tap device */ 96267186Sasomers 97267186Sasomers len = read(t, recvbuf, buflen); 98267186Sasomers if (len == 0) 99267186Sasomers errx(EXIT_FAILURE, "read returned EOF"); 100267186Sasomers else if (len < 0 && errno == EAGAIN) 101267186Sasomers errx(EXIT_FAILURE, "Did not receive any packets"); 102267186Sasomers else if (len < 0) 103267186Sasomers err(EXIT_FAILURE, "read"); 104267186Sasomers 105267186Sasomers /* 106267186Sasomers * If read returned anything at all, consider it a success. The packet 107267186Sasomers * should be an Ethernet frame containing an ARP request for 108267186Sasomers * ip_address. We won't bother to decode it 109267186Sasomers */ 110263445Sasomers return (0); 111263445Sasomers} 112