1263445Sasomers/* 2263445Sasomers * Copyright (c) 2014 Spectra Logic Corporation 3263445Sasomers * All rights reserved. 4264917Sasomers * 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. 16264917Sasomers * 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. 29264917Sasomers * 30263445Sasomers * Authors: Alan Somers (Spectra Logic Corporation) 31263445Sasomers * 32263445Sasomers * $FreeBSD: stable/11/tests/sys/netinet/udp_dontroute.c 317067 2017-04-17 20:13:20Z asomers $ 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> 42266860Sasomers#include <fcntl.h> 43263445Sasomers#include <stdio.h> 44317067Sasomers#include <stdbool.h> 45263445Sasomers#include <stdlib.h> 46263445Sasomers#include <string.h> 47266860Sasomers#include <unistd.h> 48263445Sasomers 49264917Sasomers/* 50263445Sasomers * Sends a single UDP packet to the provided address, with SO_DONTROUTE set 51263445Sasomers * I couldn't find a way to do this with builtin utilities like nc(1) 52263445Sasomers */ 53264917Sasomersint 54264917Sasomersmain(int argc, char **argv) 55263445Sasomers{ 56317067Sasomers struct sockaddr_storage dst; 57266860Sasomers int s, t; 58263445Sasomers int opt; 59263445Sasomers int ret; 60266860Sasomers ssize_t len; 61266860Sasomers const char* sendbuf = "Hello, World!"; 62266860Sasomers const size_t buflen = 80; 63266860Sasomers char recvbuf[buflen]; 64317067Sasomers bool v6 = false; 65317067Sasomers const char *addr, *tapdev; 66317067Sasomers const uint16_t port = 46120; 67263445Sasomers 68317067Sasomers bzero(&dst, sizeof(dst)); 69317067Sasomers if (argc < 3 || argc > 4) { 70317067Sasomers fprintf(stderr, "Usage: %s [-6] ip_address tapdev\n", argv[0]); 71263445Sasomers exit(2); 72263445Sasomers } 73266860Sasomers 74317067Sasomers if (strcmp("-6", argv[1]) == 0) { 75317067Sasomers v6 = true; 76317067Sasomers addr = argv[2]; 77317067Sasomers tapdev = argv[3]; 78317067Sasomers } else { 79317067Sasomers addr = argv[1]; 80317067Sasomers tapdev = argv[2]; 81317067Sasomers } 82317067Sasomers 83317067Sasomers t = open(tapdev, O_RDWR | O_NONBLOCK); 84266860Sasomers if (t < 0) 85266860Sasomers err(EXIT_FAILURE, "open"); 86266860Sasomers 87317067Sasomers if (v6) 88317067Sasomers s = socket(PF_INET6, SOCK_DGRAM, 0); 89317067Sasomers else 90317067Sasomers s = socket(PF_INET, SOCK_DGRAM, 0); 91263445Sasomers if (s < 0) 92266860Sasomers err(EXIT_FAILURE, "socket"); 93263445Sasomers opt = 1; 94263445Sasomers 95263445Sasomers ret = setsockopt(s, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt)); 96263445Sasomers if (ret == -1) 97266860Sasomers err(EXIT_FAILURE, "setsockopt(SO_DONTROUTE)"); 98263445Sasomers 99317067Sasomers if (v6) { 100317067Sasomers struct sockaddr_in6 *dst6 = ((struct sockaddr_in6*)&dst); 101317067Sasomers 102317067Sasomers dst.ss_len = sizeof(struct sockaddr_in6); 103317067Sasomers dst.ss_family = AF_INET6; 104317067Sasomers dst6->sin6_port = htons(port); 105317067Sasomers ret = inet_pton(AF_INET6, addr, &dst6->sin6_addr); 106317067Sasomers } else { 107317067Sasomers struct sockaddr_in *dst4 = ((struct sockaddr_in*)&dst); 108317067Sasomers 109317067Sasomers dst.ss_len = sizeof(struct sockaddr_in); 110317067Sasomers dst.ss_family = AF_INET; 111317067Sasomers dst4->sin_port = htons(port); 112317067Sasomers ret = inet_pton(AF_INET, addr, &dst4->sin_addr); 113263445Sasomers } 114317067Sasomers if (ret != 1) 115317067Sasomers err(EXIT_FAILURE, "inet_pton returned %d", ret); 116317067Sasomers 117266860Sasomers ret = sendto(s, sendbuf, strlen(sendbuf), 0, (struct sockaddr*)&dst, 118317067Sasomers dst.ss_len); 119263445Sasomers if (ret == -1) 120266860Sasomers err(EXIT_FAILURE, "sendto"); 121264917Sasomers 122266860Sasomers /* Verify that the packet went to the desired tap device */ 123266860Sasomers 124266860Sasomers len = read(t, recvbuf, buflen); 125266860Sasomers if (len == 0) 126266860Sasomers errx(EXIT_FAILURE, "read returned EOF"); 127266860Sasomers else if (len < 0 && errno == EAGAIN) 128266860Sasomers errx(EXIT_FAILURE, "Did not receive any packets"); 129266860Sasomers else if (len < 0) 130266860Sasomers err(EXIT_FAILURE, "read"); 131266860Sasomers 132266860Sasomers /* 133266860Sasomers * If read returned anything at all, consider it a success. The packet 134266860Sasomers * should be an Ethernet frame containing an ARP request for 135266860Sasomers * ip_address. We won't bother to decode it 136266860Sasomers */ 137263445Sasomers return (0); 138263445Sasomers} 139