Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/regression/netinet/ipdivert/ipdivert.c
39491 views
1
/*-
2
* Copyright (c) 2010-2011 Juniper Networks, Inc.
3
* All rights reserved.
4
*
5
* This software was developed by Robert N. M. Watson under contract
6
* to Juniper Networks, Inc.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/*
31
* This is a test tool for IP divert sockets. For the time being, it just
32
* exercise creation and binding of sockets, rather than their divert
33
* behaviour. It would be highly desirable to broaden this test tool to
34
* include packet injection and diversion.
35
*/
36
37
#include <sys/types.h>
38
#include <sys/socket.h>
39
40
#include <netinet/in.h>
41
42
#include <err.h>
43
#include <errno.h>
44
#include <stdio.h>
45
#include <stdlib.h>
46
#include <string.h>
47
#include <unistd.h>
48
49
static void
50
ok(const char *test)
51
{
52
53
fprintf(stderr, "%s: OK\n", test);
54
}
55
56
static void
57
fail(const char *test, const char *note)
58
{
59
60
fprintf(stderr, "%s - %s: FAIL (%s)\n", test, note, strerror(errno));
61
exit(1);
62
}
63
64
static void
65
failx(const char *test, const char *note)
66
{
67
68
fprintf(stderr, "%s - %s: FAIL\n", test, note);
69
exit(1);
70
}
71
72
static int
73
ipdivert_create(const char *test)
74
{
75
int s;
76
77
s = socket(PF_DIVERT, SOCK_RAW, 0);
78
if (s < 0)
79
fail(test, "socket");
80
return (s);
81
}
82
83
static void
84
ipdivert_close(const char *test, int s)
85
{
86
87
if (close(s) < 0)
88
fail(test, "close");
89
}
90
91
static void
92
ipdivert_bind(const char *test, int s, u_short port, int expect)
93
{
94
struct sockaddr_in sin;
95
int err;
96
97
bzero(&sin, sizeof(sin));
98
sin.sin_family = AF_INET;
99
sin.sin_addr.s_addr = htonl(INADDR_ANY);
100
sin.sin_port = htons(port);
101
102
err = bind(s, (struct sockaddr *)&sin, sizeof(sin));
103
if (err < 0) {
104
if (expect == 0)
105
fail(test, "bind");
106
if (errno != expect)
107
fail(test, "bind");
108
} else {
109
if (expect != 0)
110
failx(test, "bind");
111
}
112
}
113
114
int
115
main(int argc, char *argv[])
116
{
117
const char *test;
118
int s1, s2;
119
120
/*
121
* First test: create and close an IP divert socket.
122
*/
123
test = "create_close";
124
s1 = ipdivert_create(test);
125
ipdivert_close(test, s1);
126
ok(test);
127
128
/*
129
* Second test: create, bind, and close an IP divert socket.
130
*/
131
test = "create_bind_close";
132
s1 = ipdivert_create(test);
133
ipdivert_bind(test, s1, 1000, 0);
134
ipdivert_close(test, s1);
135
ok(test);
136
137
/*
138
* Third test: create two sockets, bind to different ports, and close.
139
* This should succeed due to non-conflict on the port numbers.
140
*/
141
test = "create2_bind2_close2";
142
s1 = ipdivert_create(test);
143
s2 = ipdivert_create(test);
144
ipdivert_bind(test, s1, 1000, 0);
145
ipdivert_bind(test, s2, 1001, 0);
146
ipdivert_close(test, s1);
147
ipdivert_close(test, s2);
148
ok(test);
149
150
/*
151
* Fourth test: create two sockets, bind to the *same* port, and
152
* close. This should fail due to conflicting port numbers.
153
*/
154
test = "create2_bind2_conflict_close2";
155
s1 = ipdivert_create(test);
156
s2 = ipdivert_create(test);
157
ipdivert_bind(test, s1, 1000, 0);
158
ipdivert_bind(test, s2, 1000, EADDRINUSE);
159
ipdivert_close(test, s1);
160
ipdivert_close(test, s2);
161
ok(test);
162
163
return (0);
164
}
165
166