17fcc404bSRobert Watson /*-
27fcc404bSRobert Watson * Copyright (c) 2010-2011 Juniper Networks, Inc.
37fcc404bSRobert Watson * All rights reserved.
47fcc404bSRobert Watson *
57fcc404bSRobert Watson * This software was developed by Robert N. M. Watson under contract
67fcc404bSRobert Watson * to Juniper Networks, Inc.
77fcc404bSRobert Watson *
87fcc404bSRobert Watson * Redistribution and use in source and binary forms, with or without
97fcc404bSRobert Watson * modification, are permitted provided that the following conditions
107fcc404bSRobert Watson * are met:
117fcc404bSRobert Watson * 1. Redistributions of source code must retain the above copyright
127fcc404bSRobert Watson * notice, this list of conditions and the following disclaimer.
137fcc404bSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
147fcc404bSRobert Watson * notice, this list of conditions and the following disclaimer in the
157fcc404bSRobert Watson * documentation and/or other materials provided with the distribution.
167fcc404bSRobert Watson *
177fcc404bSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
187fcc404bSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
197fcc404bSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
207fcc404bSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
217fcc404bSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
227fcc404bSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
237fcc404bSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
247fcc404bSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
257fcc404bSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
267fcc404bSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
277fcc404bSRobert Watson * SUCH DAMAGE.
287fcc404bSRobert Watson */
297fcc404bSRobert Watson
307fcc404bSRobert Watson /*
317fcc404bSRobert Watson * This is a test tool for IP divert sockets. For the time being, it just
327fcc404bSRobert Watson * exercise creation and binding of sockets, rather than their divert
337fcc404bSRobert Watson * behaviour. It would be highly desirable to broaden this test tool to
347fcc404bSRobert Watson * include packet injection and diversion.
357fcc404bSRobert Watson */
367fcc404bSRobert Watson
377fcc404bSRobert Watson #include <sys/types.h>
387fcc404bSRobert Watson #include <sys/socket.h>
397fcc404bSRobert Watson
407fcc404bSRobert Watson #include <netinet/in.h>
417fcc404bSRobert Watson
427fcc404bSRobert Watson #include <err.h>
437fcc404bSRobert Watson #include <errno.h>
447fcc404bSRobert Watson #include <stdio.h>
457fcc404bSRobert Watson #include <stdlib.h>
467fcc404bSRobert Watson #include <string.h>
477fcc404bSRobert Watson #include <unistd.h>
487fcc404bSRobert Watson
497fcc404bSRobert Watson static void
ok(const char * test)507fcc404bSRobert Watson ok(const char *test)
517fcc404bSRobert Watson {
527fcc404bSRobert Watson
537fcc404bSRobert Watson fprintf(stderr, "%s: OK\n", test);
547fcc404bSRobert Watson }
557fcc404bSRobert Watson
567fcc404bSRobert Watson static void
fail(const char * test,const char * note)577fcc404bSRobert Watson fail(const char *test, const char *note)
587fcc404bSRobert Watson {
597fcc404bSRobert Watson
607fcc404bSRobert Watson fprintf(stderr, "%s - %s: FAIL (%s)\n", test, note, strerror(errno));
617fcc404bSRobert Watson exit(1);
627fcc404bSRobert Watson }
637fcc404bSRobert Watson
647fcc404bSRobert Watson static void
failx(const char * test,const char * note)657fcc404bSRobert Watson failx(const char *test, const char *note)
667fcc404bSRobert Watson {
677fcc404bSRobert Watson
687fcc404bSRobert Watson fprintf(stderr, "%s - %s: FAIL\n", test, note);
697fcc404bSRobert Watson exit(1);
707fcc404bSRobert Watson }
717fcc404bSRobert Watson
727fcc404bSRobert Watson static int
ipdivert_create(const char * test)737fcc404bSRobert Watson ipdivert_create(const char *test)
747fcc404bSRobert Watson {
757fcc404bSRobert Watson int s;
767fcc404bSRobert Watson
77*4627bc1eSGleb Smirnoff s = socket(PF_DIVERT, SOCK_RAW, 0);
787fcc404bSRobert Watson if (s < 0)
797fcc404bSRobert Watson fail(test, "socket");
807fcc404bSRobert Watson return (s);
817fcc404bSRobert Watson }
827fcc404bSRobert Watson
837fcc404bSRobert Watson static void
ipdivert_close(const char * test,int s)847fcc404bSRobert Watson ipdivert_close(const char *test, int s)
857fcc404bSRobert Watson {
867fcc404bSRobert Watson
877fcc404bSRobert Watson if (close(s) < 0)
887fcc404bSRobert Watson fail(test, "close");
897fcc404bSRobert Watson }
907fcc404bSRobert Watson
917fcc404bSRobert Watson static void
ipdivert_bind(const char * test,int s,u_short port,int expect)927fcc404bSRobert Watson ipdivert_bind(const char *test, int s, u_short port, int expect)
937fcc404bSRobert Watson {
947fcc404bSRobert Watson struct sockaddr_in sin;
957fcc404bSRobert Watson int err;
967fcc404bSRobert Watson
977fcc404bSRobert Watson bzero(&sin, sizeof(sin));
987fcc404bSRobert Watson sin.sin_family = AF_INET;
997fcc404bSRobert Watson sin.sin_addr.s_addr = htonl(INADDR_ANY);
1007fcc404bSRobert Watson sin.sin_port = htons(port);
1017fcc404bSRobert Watson
1027fcc404bSRobert Watson err = bind(s, (struct sockaddr *)&sin, sizeof(sin));
1037fcc404bSRobert Watson if (err < 0) {
1047fcc404bSRobert Watson if (expect == 0)
1057fcc404bSRobert Watson fail(test, "bind");
1067fcc404bSRobert Watson if (errno != expect)
1077fcc404bSRobert Watson fail(test, "bind");
1087fcc404bSRobert Watson } else {
1097fcc404bSRobert Watson if (expect != 0)
1107fcc404bSRobert Watson failx(test, "bind");
1117fcc404bSRobert Watson }
1127fcc404bSRobert Watson }
1137fcc404bSRobert Watson
1147fcc404bSRobert Watson int
main(int argc,char * argv[])1157fcc404bSRobert Watson main(int argc, char *argv[])
1167fcc404bSRobert Watson {
1177fcc404bSRobert Watson const char *test;
1187fcc404bSRobert Watson int s1, s2;
1197fcc404bSRobert Watson
1207fcc404bSRobert Watson /*
1217fcc404bSRobert Watson * First test: create and close an IP divert socket.
1227fcc404bSRobert Watson */
1237fcc404bSRobert Watson test = "create_close";
1247fcc404bSRobert Watson s1 = ipdivert_create(test);
1257fcc404bSRobert Watson ipdivert_close(test, s1);
1267fcc404bSRobert Watson ok(test);
1277fcc404bSRobert Watson
1287fcc404bSRobert Watson /*
1297fcc404bSRobert Watson * Second test: create, bind, and close an IP divert socket.
1307fcc404bSRobert Watson */
1317fcc404bSRobert Watson test = "create_bind_close";
1327fcc404bSRobert Watson s1 = ipdivert_create(test);
1337fcc404bSRobert Watson ipdivert_bind(test, s1, 1000, 0);
1347fcc404bSRobert Watson ipdivert_close(test, s1);
1357fcc404bSRobert Watson ok(test);
1367fcc404bSRobert Watson
1377fcc404bSRobert Watson /*
1387fcc404bSRobert Watson * Third test: create two sockets, bind to different ports, and close.
1397fcc404bSRobert Watson * This should succeed due to non-conflict on the port numbers.
1407fcc404bSRobert Watson */
1417fcc404bSRobert Watson test = "create2_bind2_close2";
1427fcc404bSRobert Watson s1 = ipdivert_create(test);
1437fcc404bSRobert Watson s2 = ipdivert_create(test);
1447fcc404bSRobert Watson ipdivert_bind(test, s1, 1000, 0);
1457fcc404bSRobert Watson ipdivert_bind(test, s2, 1001, 0);
1467fcc404bSRobert Watson ipdivert_close(test, s1);
1477fcc404bSRobert Watson ipdivert_close(test, s2);
1487fcc404bSRobert Watson ok(test);
1497fcc404bSRobert Watson
1507fcc404bSRobert Watson /*
1517fcc404bSRobert Watson * Fourth test: create two sockets, bind to the *same* port, and
1527fcc404bSRobert Watson * close. This should fail due to conflicting port numbers.
1537fcc404bSRobert Watson */
1547fcc404bSRobert Watson test = "create2_bind2_conflict_close2";
1557fcc404bSRobert Watson s1 = ipdivert_create(test);
1567fcc404bSRobert Watson s2 = ipdivert_create(test);
1577fcc404bSRobert Watson ipdivert_bind(test, s1, 1000, 0);
1587fcc404bSRobert Watson ipdivert_bind(test, s2, 1000, EADDRINUSE);
1597fcc404bSRobert Watson ipdivert_close(test, s1);
1607fcc404bSRobert Watson ipdivert_close(test, s2);
1617fcc404bSRobert Watson ok(test);
1627fcc404bSRobert Watson
1637fcc404bSRobert Watson return (0);
1647fcc404bSRobert Watson }
165