Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/netpfil/common/divapp.c
39536 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2023 Igor Ostapenko <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
/* Used by divert(4) related tests */
29
30
#include <errno.h>
31
#include <stdlib.h>
32
#include <stdbool.h>
33
#include <err.h>
34
#include <sysexits.h>
35
#include <string.h>
36
37
#include <sys/types.h>
38
#include <sys/socket.h>
39
#include <netinet/in.h>
40
#include <netinet/ip.h>
41
42
43
struct context {
44
unsigned short divert_port;
45
bool divert_back;
46
47
int fd;
48
struct sockaddr_in sin;
49
socklen_t sin_len;
50
char pkt[IP_MAXPACKET];
51
ssize_t pkt_n;
52
};
53
54
static void
55
init(struct context *c)
56
{
57
c->fd = socket(PF_DIVERT, SOCK_RAW, 0);
58
if (c->fd == -1)
59
errx(EX_OSERR, "init: Cannot create divert socket.");
60
61
memset(&c->sin, 0, sizeof(c->sin));
62
c->sin.sin_family = AF_INET;
63
c->sin.sin_port = htons(c->divert_port);
64
c->sin.sin_addr.s_addr = INADDR_ANY;
65
c->sin_len = sizeof(struct sockaddr_in);
66
67
if (bind(c->fd, (struct sockaddr *) &c->sin, c->sin_len) != 0)
68
errx(EX_OSERR, "init: Cannot bind divert socket.");
69
}
70
71
static ssize_t
72
recv_pkt(struct context *c)
73
{
74
fd_set readfds;
75
struct timeval timeout;
76
int s;
77
78
FD_ZERO(&readfds);
79
FD_SET(c->fd, &readfds);
80
timeout.tv_sec = 3;
81
timeout.tv_usec = 0;
82
83
s = select(c->fd + 1, &readfds, 0, 0, &timeout);
84
if (s == -1)
85
errx(EX_IOERR, "recv_pkt: select() errors.");
86
if (s != 1) /* timeout */
87
return (-1);
88
89
c->pkt_n = recvfrom(c->fd, c->pkt, sizeof(c->pkt), 0,
90
(struct sockaddr *) &c->sin, &c->sin_len);
91
if (c->pkt_n == -1)
92
errx(EX_IOERR, "recv_pkt: recvfrom() errors.");
93
94
return (c->pkt_n);
95
}
96
97
static void
98
send_pkt(struct context *c)
99
{
100
ssize_t n;
101
102
n = sendto(c->fd, c->pkt, c->pkt_n, 0,
103
(struct sockaddr *) &c->sin, c->sin_len);
104
if (n == -1)
105
err(EX_IOERR, "send_pkt: sendto() errors");
106
if (n != c->pkt_n)
107
errx(EX_IOERR, "send_pkt: sendto() sent %zd of %zd bytes.",
108
n, c->pkt_n);
109
}
110
111
int
112
main(int argc, char *argv[])
113
{
114
struct context c;
115
int npkt;
116
117
if (argc < 2)
118
errx(EX_USAGE,
119
"Usage: %s <divert-port> [divert-back]", argv[0]);
120
121
memset(&c, 0, sizeof(struct context));
122
123
c.divert_port = (unsigned short) strtol(argv[1], NULL, 10);
124
if (c.divert_port == 0)
125
errx(EX_USAGE, "divert port is not defined.");
126
127
if (argc >= 3 && strcmp(argv[2], "divert-back") == 0)
128
c.divert_back = true;
129
130
131
init(&c);
132
133
npkt = 0;
134
while (recv_pkt(&c) > 0) {
135
if (c.divert_back)
136
send_pkt(&c);
137
npkt++;
138
if (npkt >= 10)
139
break;
140
}
141
142
if (npkt != 1)
143
errx(EXIT_FAILURE, "%d: npkt=%d.", c.divert_port, npkt);
144
145
return (EXIT_SUCCESS);
146
}
147
148