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: releng/10.3/tools/regression/netinet/ipdivert/ipdivert.c 222689 2011-06-04 16:25:12Z rwatson $
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