1222689Srwatson/*- 2222689Srwatson * Copyright (c) 2010-2011 Juniper Networks, Inc. 3222689Srwatson * All rights reserved. 4222689Srwatson * 5222689Srwatson * This software was developed by Robert N. M. Watson under contract 6222689Srwatson * to Juniper Networks, Inc. 7222689Srwatson * 8222689Srwatson * Redistribution and use in source and binary forms, with or without 9222689Srwatson * modification, are permitted provided that the following conditions 10222689Srwatson * are met: 11222689Srwatson * 1. Redistributions of source code must retain the above copyright 12222689Srwatson * notice, this list of conditions and the following disclaimer. 13222689Srwatson * 2. Redistributions in binary form must reproduce the above copyright 14222689Srwatson * notice, this list of conditions and the following disclaimer in the 15222689Srwatson * documentation and/or other materials provided with the distribution. 16222689Srwatson * 17222689Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18222689Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19222689Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20222689Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21222689Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22222689Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23222689Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24222689Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25222689Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26222689Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27222689Srwatson * SUCH DAMAGE. 28222689Srwatson * 29222689Srwatson * $FreeBSD$ 30222689Srwatson */ 31222689Srwatson 32222689Srwatson/* 33222689Srwatson * This is a test tool for IP divert sockets. For the time being, it just 34222689Srwatson * exercise creation and binding of sockets, rather than their divert 35222689Srwatson * behaviour. It would be highly desirable to broaden this test tool to 36222689Srwatson * include packet injection and diversion. 37222689Srwatson */ 38222689Srwatson 39222689Srwatson#include <sys/types.h> 40222689Srwatson#include <sys/socket.h> 41222689Srwatson 42222689Srwatson#include <netinet/in.h> 43222689Srwatson 44222689Srwatson#include <err.h> 45222689Srwatson#include <errno.h> 46222689Srwatson#include <stdio.h> 47222689Srwatson#include <stdlib.h> 48222689Srwatson#include <string.h> 49222689Srwatson#include <unistd.h> 50222689Srwatson 51222689Srwatsonstatic void 52222689Srwatsonok(const char *test) 53222689Srwatson{ 54222689Srwatson 55222689Srwatson fprintf(stderr, "%s: OK\n", test); 56222689Srwatson} 57222689Srwatson 58222689Srwatsonstatic void 59222689Srwatsonfail(const char *test, const char *note) 60222689Srwatson{ 61222689Srwatson 62222689Srwatson fprintf(stderr, "%s - %s: FAIL (%s)\n", test, note, strerror(errno)); 63222689Srwatson exit(1); 64222689Srwatson} 65222689Srwatson 66222689Srwatsonstatic void 67222689Srwatsonfailx(const char *test, const char *note) 68222689Srwatson{ 69222689Srwatson 70222689Srwatson fprintf(stderr, "%s - %s: FAIL\n", test, note); 71222689Srwatson exit(1); 72222689Srwatson} 73222689Srwatson 74222689Srwatsonstatic int 75222689Srwatsonipdivert_create(const char *test) 76222689Srwatson{ 77222689Srwatson int s; 78222689Srwatson 79222689Srwatson s = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT); 80222689Srwatson if (s < 0) 81222689Srwatson fail(test, "socket"); 82222689Srwatson return (s); 83222689Srwatson} 84222689Srwatson 85222689Srwatsonstatic void 86222689Srwatsonipdivert_close(const char *test, int s) 87222689Srwatson{ 88222689Srwatson 89222689Srwatson if (close(s) < 0) 90222689Srwatson fail(test, "close"); 91222689Srwatson} 92222689Srwatson 93222689Srwatsonstatic void 94222689Srwatsonipdivert_bind(const char *test, int s, u_short port, int expect) 95222689Srwatson{ 96222689Srwatson struct sockaddr_in sin; 97222689Srwatson int err; 98222689Srwatson 99222689Srwatson bzero(&sin, sizeof(sin)); 100222689Srwatson sin.sin_family = AF_INET; 101222689Srwatson sin.sin_addr.s_addr = htonl(INADDR_ANY); 102222689Srwatson sin.sin_port = htons(port); 103222689Srwatson 104222689Srwatson err = bind(s, (struct sockaddr *)&sin, sizeof(sin)); 105222689Srwatson if (err < 0) { 106222689Srwatson if (expect == 0) 107222689Srwatson fail(test, "bind"); 108222689Srwatson if (errno != expect) 109222689Srwatson fail(test, "bind"); 110222689Srwatson } else { 111222689Srwatson if (expect != 0) 112222689Srwatson failx(test, "bind"); 113222689Srwatson } 114222689Srwatson} 115222689Srwatson 116222689Srwatsonint 117222689Srwatsonmain(int argc, char *argv[]) 118222689Srwatson{ 119222689Srwatson const char *test; 120222689Srwatson int s1, s2; 121222689Srwatson 122222689Srwatson /* 123222689Srwatson * First test: create and close an IP divert socket. 124222689Srwatson */ 125222689Srwatson test = "create_close"; 126222689Srwatson s1 = ipdivert_create(test); 127222689Srwatson ipdivert_close(test, s1); 128222689Srwatson ok(test); 129222689Srwatson 130222689Srwatson /* 131222689Srwatson * Second test: create, bind, and close an IP divert socket. 132222689Srwatson */ 133222689Srwatson test = "create_bind_close"; 134222689Srwatson s1 = ipdivert_create(test); 135222689Srwatson ipdivert_bind(test, s1, 1000, 0); 136222689Srwatson ipdivert_close(test, s1); 137222689Srwatson ok(test); 138222689Srwatson 139222689Srwatson /* 140222689Srwatson * Third test: create two sockets, bind to different ports, and close. 141222689Srwatson * This should succeed due to non-conflict on the port numbers. 142222689Srwatson */ 143222689Srwatson test = "create2_bind2_close2"; 144222689Srwatson s1 = ipdivert_create(test); 145222689Srwatson s2 = ipdivert_create(test); 146222689Srwatson ipdivert_bind(test, s1, 1000, 0); 147222689Srwatson ipdivert_bind(test, s2, 1001, 0); 148222689Srwatson ipdivert_close(test, s1); 149222689Srwatson ipdivert_close(test, s2); 150222689Srwatson ok(test); 151222689Srwatson 152222689Srwatson /* 153222689Srwatson * Fourth test: create two sockets, bind to the *same* port, and 154222689Srwatson * close. This should fail due to conflicting port numbers. 155222689Srwatson */ 156222689Srwatson test = "create2_bind2_conflict_close2"; 157222689Srwatson s1 = ipdivert_create(test); 158222689Srwatson s2 = ipdivert_create(test); 159222689Srwatson ipdivert_bind(test, s1, 1000, 0); 160222689Srwatson ipdivert_bind(test, s2, 1000, EADDRINUSE); 161222689Srwatson ipdivert_close(test, s1); 162222689Srwatson ipdivert_close(test, s2); 163222689Srwatson ok(test); 164222689Srwatson 165222689Srwatson return (0); 166222689Srwatson} 167