Path: blob/main/tools/regression/netinet/ipdivert/ipdivert.c
39491 views
/*-1* Copyright (c) 2010-2011 Juniper Networks, Inc.2* All rights reserved.3*4* This software was developed by Robert N. M. Watson under contract5* to Juniper Networks, Inc.6*7* Redistribution and use in source and binary forms, with or without8* modification, are permitted provided that the following conditions9* are met:10* 1. Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND17* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE18* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE19* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE20* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL21* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS22* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)23* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT24* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY25* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF26* SUCH DAMAGE.27*/2829/*30* This is a test tool for IP divert sockets. For the time being, it just31* exercise creation and binding of sockets, rather than their divert32* behaviour. It would be highly desirable to broaden this test tool to33* include packet injection and diversion.34*/3536#include <sys/types.h>37#include <sys/socket.h>3839#include <netinet/in.h>4041#include <err.h>42#include <errno.h>43#include <stdio.h>44#include <stdlib.h>45#include <string.h>46#include <unistd.h>4748static void49ok(const char *test)50{5152fprintf(stderr, "%s: OK\n", test);53}5455static void56fail(const char *test, const char *note)57{5859fprintf(stderr, "%s - %s: FAIL (%s)\n", test, note, strerror(errno));60exit(1);61}6263static void64failx(const char *test, const char *note)65{6667fprintf(stderr, "%s - %s: FAIL\n", test, note);68exit(1);69}7071static int72ipdivert_create(const char *test)73{74int s;7576s = socket(PF_DIVERT, SOCK_RAW, 0);77if (s < 0)78fail(test, "socket");79return (s);80}8182static void83ipdivert_close(const char *test, int s)84{8586if (close(s) < 0)87fail(test, "close");88}8990static void91ipdivert_bind(const char *test, int s, u_short port, int expect)92{93struct sockaddr_in sin;94int err;9596bzero(&sin, sizeof(sin));97sin.sin_family = AF_INET;98sin.sin_addr.s_addr = htonl(INADDR_ANY);99sin.sin_port = htons(port);100101err = bind(s, (struct sockaddr *)&sin, sizeof(sin));102if (err < 0) {103if (expect == 0)104fail(test, "bind");105if (errno != expect)106fail(test, "bind");107} else {108if (expect != 0)109failx(test, "bind");110}111}112113int114main(int argc, char *argv[])115{116const char *test;117int s1, s2;118119/*120* First test: create and close an IP divert socket.121*/122test = "create_close";123s1 = ipdivert_create(test);124ipdivert_close(test, s1);125ok(test);126127/*128* Second test: create, bind, and close an IP divert socket.129*/130test = "create_bind_close";131s1 = ipdivert_create(test);132ipdivert_bind(test, s1, 1000, 0);133ipdivert_close(test, s1);134ok(test);135136/*137* Third test: create two sockets, bind to different ports, and close.138* This should succeed due to non-conflict on the port numbers.139*/140test = "create2_bind2_close2";141s1 = ipdivert_create(test);142s2 = ipdivert_create(test);143ipdivert_bind(test, s1, 1000, 0);144ipdivert_bind(test, s2, 1001, 0);145ipdivert_close(test, s1);146ipdivert_close(test, s2);147ok(test);148149/*150* Fourth test: create two sockets, bind to the *same* port, and151* close. This should fail due to conflicting port numbers.152*/153test = "create2_bind2_conflict_close2";154s1 = ipdivert_create(test);155s2 = ipdivert_create(test);156ipdivert_bind(test, s1, 1000, 0);157ipdivert_bind(test, s2, 1000, EADDRINUSE);158ipdivert_close(test, s1);159ipdivert_close(test, s2);160ok(test);161162return (0);163}164165166