1/* 2 * Copyright (c) 2014 Spectra Logic Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * substantially similar to the "NO WARRANTY" disclaimer below 13 * ("Disclaimer") and any redistribution must be conditioned upon 14 * including a substantially similar Disclaimer requirement for further 15 * binary redistribution. 16 * 17 * NO WARRANTY 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGES. 29 * 30 * Authors: Alan Somers (Spectra Logic Corporation) 31 * 32 * $FreeBSD$ 33 */ 34 35#include <arpa/inet.h> 36#include <netinet/in.h> 37#include <sys/types.h> 38#include <sys/socket.h> 39 40#include <err.h> 41#include <errno.h> 42#include <fcntl.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48/* 49 * Sends a single UDP packet to the provided address, with SO_DONTROUTE set 50 * I couldn't find a way to do this with builtin utilities like nc(1) 51 */ 52int 53main(int argc, char **argv) 54{ 55 struct sockaddr_in dst; 56 int s, t; 57 int opt; 58 int ret; 59 ssize_t len; 60 const char* sendbuf = "Hello, World!"; 61 const size_t buflen = 80; 62 char recvbuf[buflen]; 63 64 if (argc != 3) { 65 fprintf(stderr, "Usage: %s ip_address tapdev\n", argv[0]); 66 exit(2); 67 } 68 69 t = open(argv[2], O_RDWR | O_NONBLOCK); 70 if (t < 0) 71 err(EXIT_FAILURE, "open"); 72 73 s = socket(PF_INET, SOCK_DGRAM, 0); 74 if (s < 0) 75 err(EXIT_FAILURE, "socket"); 76 opt = 1; 77 78 ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt)); 79 if (ret == -1) 80 err(EXIT_FAILURE, "setsockopt(SO_DONTROUTE)"); 81 82 dst.sin_len = sizeof(dst); 83 dst.sin_family = AF_INET; 84 dst.sin_port = htons(46120); 85 dst.sin_addr.s_addr = inet_addr(argv[1]); 86 if (dst.sin_addr.s_addr == htonl(INADDR_NONE)) { 87 fprintf(stderr, "Invalid address: %s\n", argv[1]); 88 exit(2); 89 } 90 ret = sendto(s, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&dst, 91 dst.sin_len); 92 if (ret == -1) 93 err(EXIT_FAILURE, "sendto"); 94 95 /* Verify that the packet went to the desired tap device */ 96 97 len = read(t, recvbuf, buflen); 98 if (len == 0) 99 errx(EXIT_FAILURE, "read returned EOF"); 100 else if (len < 0 && errno == EAGAIN) 101 errx(EXIT_FAILURE, "Did not receive any packets"); 102 else if (len < 0) 103 err(EXIT_FAILURE, "read"); 104 105 /* 106 * If read returned anything at all, consider it a success. The packet 107 * should be an Ethernet frame containing an ARP request for 108 * ip_address. We won't bother to decode it 109 */ 110 return (0); 111} 112