xref: /openbsd/regress/sys/net/pflow/gen_traffic.c (revision cecf84d4)
1 /*	$OpenBSD: gen_traffic.c,v 1.1 2013/08/23 08:25:58 florian 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 		err(1, "%s", "connect");
131 	event_set(&sender->ev, s, EV_WRITE | EV_PERSIST, gen_traffic_write,
132 	    sender);
133 	event_add(&sender->ev, NULL);
134 	evtimer_set(&sender->pause, gen_traffic_sender_paused, sender);
135 	event_dispatch();
136 	exit(0);
137 }
138 
139 void
140 gen_traffic_paused(int fd, short events, void *arg)
141 {
142 	struct listener	*l = arg;
143 	event_add(&l->ev, NULL);
144 }
145 
146 void
147 gen_traffic_sender_paused(int fd, short events, void *arg)
148 {
149 	struct sender	*s = arg;
150 	event_add(&s->ev, NULL);
151 }
152 
153 void
154 gen_traffic_accept(int fd, short events, void *arg)
155 {
156 	struct listener		*l;
157 	struct sockaddr_storage	 ss;
158 	struct timeval		 pause;
159 	struct reader		*r;
160 	socklen_t		 len;
161 	int			 s;
162 
163 	l = arg;
164 	pause.tv_sec = 1; pause.tv_usec = 0;
165 
166 	len = sizeof(ss);
167 	s = accept(fd, (struct sockaddr *)&ss, &len);
168 	if (s == -1) {
169 		switch (errno) {
170 		case EINTR:
171 		case EWOULDBLOCK:
172 		case ECONNABORTED:
173 			return;
174 		case EMFILE:
175 		case ENFILE:
176 			event_del(&l->ev);
177 			evtimer_add(&l->pause, &pause);
178 			return;
179 		default:
180 			err(1, "%s", "accept");
181 		}
182 	}
183 
184 	if (ioctl(s, FIONBIO, &on) == -1)
185 		err(1, "%s", "reader ioctl(FIONBIO)");
186 
187 	r = calloc(1, sizeof(*r));
188 	if (r == NULL)
189 		errx(1, "%s", "cannot calloc reader");
190 
191 	r->fd = s;
192 
193 	event_set(&r->ev, s, EV_READ | EV_PERSIST, gen_traffic_request, r);
194 	event_add(&r->ev, NULL);
195 }
196 
197 void
198 gen_traffic_request(int fd, short events, void *arg)
199 {
200 	static size_t	 total = 0;
201 	struct reader	*r;
202 	size_t 		 n;
203 	uint8_t		 buf[4096];
204 
205 	r = arg;
206 
207 	n = read(fd, buf, 4096);
208 
209 	switch (n) {
210 	case -1:
211 		switch (errno) {
212 		case EINTR:
213 		case EAGAIN:
214 			return;
215 		default:
216 			err(1, "%s", "read");
217 		}
218 		break;
219 
220 	case 0:
221 		event_del(&r->ev);
222 		close(fd);
223 		break;
224 	default:
225 		total += n;
226 		/* warnx("read: %lld - %lld", n, total); */
227 		break;
228 	}
229 	if (total == 10 * 4096) {
230 		/* warnx("done %lld", total); */
231 		exit(0);
232 	}
233 }
234 
235 void
236 gen_traffic_write(int fd, short events, void *arg)
237 {
238 	static int	 count = 0;
239 	struct timeval	 pause;
240 	struct sender	*s;
241 	uint8_t		 buf[4096];
242 
243 	s = arg;
244 	pause.tv_sec = 1;
245 	pause.tv_usec = 0;
246 	event_del(&s->ev);
247 	if (count++ >= 10) {
248 		/* warnx("%s", "done writing"); */
249 		close(fd);
250 		return;
251 	}
252 	if (write(fd, buf, 4096) == -1)
253 		err(1, "%s", "write");
254 	evtimer_add(&s->pause, &pause);
255 }
256