xref: /openbsd/regress/sys/net/pflow/gen_traffic.c (revision ce4bf6ad)
1*ce4bf6adSmbuhl /*	$OpenBSD: gen_traffic.c,v 1.3 2022/05/31 19:01:46 mbuhl Exp $ */
2b5ac7c87Sflorian /*
3b5ac7c87Sflorian  * Copyright (c) 2013 Florian Obser <florian@openbsd.org>
4b5ac7c87Sflorian  *
5b5ac7c87Sflorian  * Permission to use, copy, modify, and distribute this software for any
6b5ac7c87Sflorian  * purpose with or without fee is hereby granted, provided that the above
7b5ac7c87Sflorian  * copyright notice and this permission notice appear in all copies.
8b5ac7c87Sflorian  *
9b5ac7c87Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10b5ac7c87Sflorian  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11b5ac7c87Sflorian  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12b5ac7c87Sflorian  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13b5ac7c87Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14b5ac7c87Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15b5ac7c87Sflorian  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16b5ac7c87Sflorian  */
17b5ac7c87Sflorian 
18b5ac7c87Sflorian #include <sys/types.h>
19b5ac7c87Sflorian #include <sys/ioctl.h>
20b5ac7c87Sflorian #include <sys/queue.h>
21b5ac7c87Sflorian #include <sys/socket.h>
22b5ac7c87Sflorian #include <sys/socketvar.h>
23b5ac7c87Sflorian #include <sys/stat.h>
24b5ac7c87Sflorian #include <sys/un.h>
25b5ac7c87Sflorian #include <sys/wait.h>
26b5ac7c87Sflorian #include <err.h>
27b5ac7c87Sflorian #include <ctype.h>
28b5ac7c87Sflorian #include <errno.h>
29b5ac7c87Sflorian #include <event.h>
30b5ac7c87Sflorian #include <netdb.h>
31b5ac7c87Sflorian #include <pwd.h>
32b5ac7c87Sflorian #include <signal.h>
33b5ac7c87Sflorian #include <stdio.h>
34b5ac7c87Sflorian #include <stdlib.h>
35b5ac7c87Sflorian #include <string.h>
36b5ac7c87Sflorian #include <syslog.h>
37b5ac7c87Sflorian #include <unistd.h>
38b5ac7c87Sflorian 
39b5ac7c87Sflorian __dead void	usage(void);
40b5ac7c87Sflorian void		gen_traffic_paused(int, short, void*);
41b5ac7c87Sflorian void		gen_traffic_accept(int, short, void*);
42b5ac7c87Sflorian void		gen_traffic_request(int, short, void*);
43b5ac7c87Sflorian void		gen_traffic_write(int, short, void*);
44b5ac7c87Sflorian void		gen_traffic_sender_paused(int, short, void*);
45b5ac7c87Sflorian 
46b5ac7c87Sflorian struct listener {
47b5ac7c87Sflorian 	struct event	ev, pause;
48b5ac7c87Sflorian };
49b5ac7c87Sflorian 
50b5ac7c87Sflorian struct reader {
51b5ac7c87Sflorian 	struct event	ev;
52b5ac7c87Sflorian 	int		fd;
53b5ac7c87Sflorian };
54b5ac7c87Sflorian 
55b5ac7c87Sflorian struct sender {
56b5ac7c87Sflorian 	struct event	ev, pause;
57b5ac7c87Sflorian 	int		fd;
58b5ac7c87Sflorian };
59b5ac7c87Sflorian 
60b5ac7c87Sflorian __dead void
usage(void)61b5ac7c87Sflorian usage(void)
62b5ac7c87Sflorian {
63b5ac7c87Sflorian 	extern char *__progname;
64b5ac7c87Sflorian 	fprintf(stderr, "usage: %s 4|6\n", __progname);
65b5ac7c87Sflorian 	exit(1);
66b5ac7c87Sflorian }
67b5ac7c87Sflorian 
68b5ac7c87Sflorian 
69b5ac7c87Sflorian int on = 1;
70b5ac7c87Sflorian 
71b5ac7c87Sflorian int
main(int argc,char * argv[])72b5ac7c87Sflorian main(int argc, char *argv[])
73b5ac7c87Sflorian {
74b5ac7c87Sflorian 	struct addrinfo  hints, *sender_res, *server_res;
75b5ac7c87Sflorian 	struct listener *l;
76b5ac7c87Sflorian 	struct sender	*sender;
77b5ac7c87Sflorian 	char		*ip;
78b5ac7c87Sflorian 	int		 error, s;
79b5ac7c87Sflorian 
80b5ac7c87Sflorian 	if (argc != 2)
81b5ac7c87Sflorian 		usage();
82b5ac7c87Sflorian 	if (strncmp(argv[1], "4", 1) == 0)
83b5ac7c87Sflorian 		ip = "10.11.12.13";
84b5ac7c87Sflorian 	else if (strncmp(argv[1], "6", 1) == 0)
85b5ac7c87Sflorian 		ip = "2001:db8::13";
86b5ac7c87Sflorian 	else
87b5ac7c87Sflorian 		usage();
88b5ac7c87Sflorian 
89b5ac7c87Sflorian 	event_init();
90b5ac7c87Sflorian 
91b5ac7c87Sflorian 	memset(&hints, 0, sizeof(hints));
92b5ac7c87Sflorian 	hints.ai_family = PF_UNSPEC;
93b5ac7c87Sflorian 	hints.ai_socktype = SOCK_STREAM;
94b5ac7c87Sflorian 	error = getaddrinfo(ip, "12346", &hints, &server_res);
95b5ac7c87Sflorian 	if (error)
96b5ac7c87Sflorian 		errx(1, "%s", gai_strerror(error));
97b5ac7c87Sflorian 	s = socket(server_res->ai_family, server_res->ai_socktype,
98b5ac7c87Sflorian 		    server_res->ai_protocol);
99b5ac7c87Sflorian 	if (s == -1)
100b5ac7c87Sflorian 		err(1, "%s", "bind");
101b5ac7c87Sflorian 	if (bind(s, server_res->ai_addr, server_res->ai_addrlen) < 0)
102b5ac7c87Sflorian 		err(1, "%s", "bind");
103b5ac7c87Sflorian 	if (ioctl(s, FIONBIO, &on) == -1)
104b5ac7c87Sflorian 		err(1, "%s", "listener ioctl(FIONBIO)");
105b5ac7c87Sflorian 	if (listen(s, 5) == -1)
106b5ac7c87Sflorian 		err(1, "%s", "listen");
107b5ac7c87Sflorian 
108b5ac7c87Sflorian 	l = calloc(1, sizeof(*l));
109b5ac7c87Sflorian 	if (l == NULL)
110b5ac7c87Sflorian 		errx(1, "calloc");
111b5ac7c87Sflorian 	event_set(&l->ev, s, EV_READ | EV_PERSIST, gen_traffic_accept, l);
112b5ac7c87Sflorian 	event_add(&l->ev, NULL);
113b5ac7c87Sflorian 	evtimer_set(&l->pause, gen_traffic_paused, l);
114b5ac7c87Sflorian 
115b5ac7c87Sflorian 	error = getaddrinfo(ip, "12345", &hints, &sender_res);
116b5ac7c87Sflorian 	if (error)
117b5ac7c87Sflorian 		errx(1, "%s", gai_strerror(error));
118b5ac7c87Sflorian 	s = socket(sender_res->ai_family, sender_res->ai_socktype,
119b5ac7c87Sflorian 		    sender_res->ai_protocol);
120b5ac7c87Sflorian 	if (s == -1)
121b5ac7c87Sflorian 		err(1, "%s", "bind");
122b5ac7c87Sflorian 	if (bind(s, sender_res->ai_addr, sender_res->ai_addrlen) < 0)
123b5ac7c87Sflorian 		err(1, "%s", "bind");
124b5ac7c87Sflorian 	if (ioctl(s, FIONBIO, &on) == -1)
125b5ac7c87Sflorian 		err(1, "%s", "sender ioctl(FIONBIO)");
126b5ac7c87Sflorian 	sender = calloc(1, sizeof(*sender));
127b5ac7c87Sflorian 	if (sender == NULL)
128b5ac7c87Sflorian 		errx(1, "calloc");
129b3e4b791Sbluhm 	if (connect(s, server_res->ai_addr, server_res->ai_addrlen) == -1 &&
130b3e4b791Sbluhm 	    errno != EINPROGRESS)
131b5ac7c87Sflorian 		err(1, "%s", "connect");
132b5ac7c87Sflorian 	event_set(&sender->ev, s, EV_WRITE | EV_PERSIST, gen_traffic_write,
133b5ac7c87Sflorian 	    sender);
134b5ac7c87Sflorian 	event_add(&sender->ev, NULL);
135b5ac7c87Sflorian 	evtimer_set(&sender->pause, gen_traffic_sender_paused, sender);
136b5ac7c87Sflorian 	event_dispatch();
137b5ac7c87Sflorian 	exit(0);
138b5ac7c87Sflorian }
139b5ac7c87Sflorian 
140b5ac7c87Sflorian void
gen_traffic_paused(int fd,short events,void * arg)141b5ac7c87Sflorian gen_traffic_paused(int fd, short events, void *arg)
142b5ac7c87Sflorian {
143b5ac7c87Sflorian 	struct listener	*l = arg;
144b5ac7c87Sflorian 	event_add(&l->ev, NULL);
145b5ac7c87Sflorian }
146b5ac7c87Sflorian 
147b5ac7c87Sflorian void
gen_traffic_sender_paused(int fd,short events,void * arg)148b5ac7c87Sflorian gen_traffic_sender_paused(int fd, short events, void *arg)
149b5ac7c87Sflorian {
150b5ac7c87Sflorian 	struct sender	*s = arg;
151b5ac7c87Sflorian 	event_add(&s->ev, NULL);
152b5ac7c87Sflorian }
153b5ac7c87Sflorian 
154b5ac7c87Sflorian void
gen_traffic_accept(int fd,short events,void * arg)155b5ac7c87Sflorian gen_traffic_accept(int fd, short events, void *arg)
156b5ac7c87Sflorian {
157b5ac7c87Sflorian 	struct listener		*l;
158b5ac7c87Sflorian 	struct sockaddr_storage	 ss;
159b5ac7c87Sflorian 	struct timeval		 pause;
160b5ac7c87Sflorian 	struct reader		*r;
161b5ac7c87Sflorian 	socklen_t		 len;
162b5ac7c87Sflorian 	int			 s;
163b5ac7c87Sflorian 
164b5ac7c87Sflorian 	l = arg;
165b5ac7c87Sflorian 	pause.tv_sec = 1; pause.tv_usec = 0;
166b5ac7c87Sflorian 
167b5ac7c87Sflorian 	len = sizeof(ss);
168b5ac7c87Sflorian 	s = accept(fd, (struct sockaddr *)&ss, &len);
169b5ac7c87Sflorian 	if (s == -1) {
170b5ac7c87Sflorian 		switch (errno) {
171b5ac7c87Sflorian 		case EINTR:
172b5ac7c87Sflorian 		case EWOULDBLOCK:
173b5ac7c87Sflorian 		case ECONNABORTED:
174b5ac7c87Sflorian 			return;
175b5ac7c87Sflorian 		case EMFILE:
176b5ac7c87Sflorian 		case ENFILE:
177b5ac7c87Sflorian 			event_del(&l->ev);
178b5ac7c87Sflorian 			evtimer_add(&l->pause, &pause);
179b5ac7c87Sflorian 			return;
180b5ac7c87Sflorian 		default:
181b5ac7c87Sflorian 			err(1, "%s", "accept");
182b5ac7c87Sflorian 		}
183b5ac7c87Sflorian 	}
184b5ac7c87Sflorian 
185b5ac7c87Sflorian 	if (ioctl(s, FIONBIO, &on) == -1)
186b5ac7c87Sflorian 		err(1, "%s", "reader ioctl(FIONBIO)");
187b5ac7c87Sflorian 
188b5ac7c87Sflorian 	r = calloc(1, sizeof(*r));
189b5ac7c87Sflorian 	if (r == NULL)
190b5ac7c87Sflorian 		errx(1, "%s", "cannot calloc reader");
191b5ac7c87Sflorian 
192b5ac7c87Sflorian 	r->fd = s;
193b5ac7c87Sflorian 
194b5ac7c87Sflorian 	event_set(&r->ev, s, EV_READ | EV_PERSIST, gen_traffic_request, r);
195b5ac7c87Sflorian 	event_add(&r->ev, NULL);
196b5ac7c87Sflorian }
197b5ac7c87Sflorian 
198b5ac7c87Sflorian void
gen_traffic_request(int fd,short events,void * arg)199b5ac7c87Sflorian gen_traffic_request(int fd, short events, void *arg)
200b5ac7c87Sflorian {
201b5ac7c87Sflorian 	static size_t	 total = 0;
202b5ac7c87Sflorian 	struct reader	*r;
203b5ac7c87Sflorian 	size_t		 n;
204b5ac7c87Sflorian 	uint8_t		 buf[4096];
205b5ac7c87Sflorian 
206b5ac7c87Sflorian 	r = arg;
207b5ac7c87Sflorian 
208b5ac7c87Sflorian 	n = read(fd, buf, 4096);
209b5ac7c87Sflorian 
210b5ac7c87Sflorian 	switch (n) {
211b5ac7c87Sflorian 	case -1:
212b5ac7c87Sflorian 		switch (errno) {
213b5ac7c87Sflorian 		case EINTR:
214b5ac7c87Sflorian 		case EAGAIN:
215b5ac7c87Sflorian 			return;
216b5ac7c87Sflorian 		default:
217b5ac7c87Sflorian 			err(1, "%s", "read");
218b5ac7c87Sflorian 		}
219b5ac7c87Sflorian 		break;
220b5ac7c87Sflorian 
221b5ac7c87Sflorian 	case 0:
222*ce4bf6adSmbuhl 		exit(0);
223b5ac7c87Sflorian 	default:
224b5ac7c87Sflorian 		total += n;
225b5ac7c87Sflorian 		/* warnx("read: %lld - %lld", n, total); */
226b5ac7c87Sflorian 		break;
227b5ac7c87Sflorian 	}
228b5ac7c87Sflorian }
229b5ac7c87Sflorian 
230b5ac7c87Sflorian void
gen_traffic_write(int fd,short events,void * arg)231b5ac7c87Sflorian gen_traffic_write(int fd, short events, void *arg)
232b5ac7c87Sflorian {
233b5ac7c87Sflorian 	static int	 count = 0;
234b5ac7c87Sflorian 	struct timeval	 pause;
235b5ac7c87Sflorian 	struct sender	*s;
236b5ac7c87Sflorian 	uint8_t		 buf[4096];
237b5ac7c87Sflorian 
238b5ac7c87Sflorian 	s = arg;
239b5ac7c87Sflorian 	pause.tv_sec = 1;
240b5ac7c87Sflorian 	pause.tv_usec = 0;
241b5ac7c87Sflorian 	event_del(&s->ev);
242b5ac7c87Sflorian 	if (count++ >= 10) {
243b5ac7c87Sflorian 		/* warnx("%s", "done writing"); */
244b5ac7c87Sflorian 		close(fd);
245b5ac7c87Sflorian 		return;
246b5ac7c87Sflorian 	}
247b5ac7c87Sflorian 	if (write(fd, buf, 4096) == -1)
248b5ac7c87Sflorian 		err(1, "%s", "write");
249b5ac7c87Sflorian 	evtimer_add(&s->pause, &pause);
250b5ac7c87Sflorian }
251