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