xref: /openbsd-src/usr.bin/tcpbench/tcpbench.c (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1 /*	$OpenBSD: tcpbench.c,v 1.59 2018/09/28 19:01:52 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Damien Miller <djm@mindrot.org>
5  * Copyright (c) 2011 Christiano F. Haesbaert <haesbaert@haesbaert.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/time.h>
22 #include <sys/socket.h>
23 #include <sys/socketvar.h>
24 #include <sys/resource.h>
25 #include <sys/queue.h>
26 #include <sys/un.h>
27 
28 #include <net/route.h>
29 
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <netinet/tcp.h>
33 #include <netinet/tcp_timer.h>
34 #include <netinet/tcp_fsm.h>
35 #include <netinet/in_pcb.h>
36 #include <netinet/tcp_var.h>
37 
38 #include <arpa/inet.h>
39 
40 #include <unistd.h>
41 #include <limits.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <event.h>
47 #include <netdb.h>
48 #include <signal.h>
49 #include <err.h>
50 #include <fcntl.h>
51 #include <poll.h>
52 #include <paths.h>
53 
54 #include <kvm.h>
55 #include <nlist.h>
56 
57 #define DEFAULT_PORT "12345"
58 #define DEFAULT_STATS_INTERVAL 1000 /* ms */
59 #define DEFAULT_BUF (256 * 1024)
60 #define DEFAULT_UDP_PKT (1500 - 28) /* TODO don't hardcode this */
61 #define TCP_MODE !ptb->uflag
62 #define UDP_MODE ptb->uflag
63 #define MAX_FD 1024
64 
65 /* Our tcpbench globals */
66 struct {
67 	int	  Sflag;	/* Socket buffer size */
68 	u_int	  rflag;	/* Report rate (ms) */
69 	int	  sflag;	/* True if server */
70 	int	  Tflag;	/* ToS if != -1 */
71 	int	  vflag;	/* Verbose */
72 	int	  uflag;	/* UDP mode */
73 	int	  Uflag;	/* UNIX (AF_LOCAL) mode */
74 	int	  Rflag;	/* randomize client write size */
75 	kvm_t	 *kvmh;		/* Kvm handler */
76 	char	**kvars;	/* Kvm enabled vars */
77 	u_long	  ktcbtab;	/* Ktcb */
78 	char	 *dummybuf;	/* IO buffer */
79 	size_t	  dummybuf_len;	/* IO buffer len */
80 } tcpbench, *ptb;
81 
82 struct tcpservsock {
83 	struct event ev;
84 	struct event evt;
85 	int fd;
86 };
87 
88 /* stats for a single tcp connection, udp uses only one  */
89 struct statctx {
90 	TAILQ_ENTRY(statctx) entry;
91 	struct timeval t_start, t_last;
92 	unsigned long long bytes;
93 	int fd;
94 	char *buf;
95 	size_t buflen;
96 	struct event ev;
97 	/* TCP only */
98 	struct tcpservsock *tcp_ts;
99 	u_long tcp_tcbaddr;
100 	/* UDP only */
101 	u_long udp_slice_pkts;
102 };
103 
104 static void	signal_handler(int, short, void *);
105 static void	saddr_ntop(const struct sockaddr *, socklen_t, char *, size_t);
106 static void	drop_gid(void);
107 static void	set_slice_timer(int);
108 static void	print_tcp_header(void);
109 static void	kget(u_long, void *, size_t);
110 static u_long	kfind_tcb(int);
111 static void	kupdate_stats(u_long, struct inpcb *, struct tcpcb *,
112     struct socket *);
113 static void	list_kvars(void);
114 static void	check_kvar(const char *);
115 static char **	check_prepare_kvars(char *);
116 static void	stats_prepare(struct statctx *);
117 static void	tcp_stats_display(unsigned long long, long double, float,
118     struct statctx *, struct inpcb *, struct tcpcb *, struct socket *);
119 static void	tcp_process_slice(int, short, void *);
120 static void	tcp_server_handle_sc(int, short, void *);
121 static void	tcp_server_accept(int, short, void *);
122 static void	server_init(struct addrinfo *, struct statctx *);
123 static void	client_handle_sc(int, short, void *);
124 static void	client_init(struct addrinfo *, int, struct statctx *,
125     struct addrinfo *);
126 static int	clock_gettime_tv(clockid_t, struct timeval *);
127 static void	udp_server_handle_sc(int, short, void *);
128 static void	udp_process_slice(int, short, void *);
129 static int	map_tos(char *, int *);
130 /*
131  * We account the mainstats here, that is the stats
132  * for all connections, all variables starting with slice
133  * are used to account information for the timeslice
134  * between each output. Peak variables record the highest
135  * between all slices so far.
136  */
137 static struct {
138 	unsigned long long slice_bytes; /* bytes for last slice */
139 	long double peak_mbps;		/* peak mbps so far */
140 	int nconns;		        /* connected clients */
141 	struct event timer;		/* process timer */
142 } mainstats;
143 
144 /* When adding variables, also add to tcp_stats_display() */
145 static const char *allowed_kvars[] = {
146 	"inpcb.inp_flags",
147 	"sockb.so_rcv.sb_cc",
148 	"sockb.so_rcv.sb_hiwat",
149 	"sockb.so_rcv.sb_wat",
150 	"sockb.so_snd.sb_cc",
151 	"sockb.so_snd.sb_hiwat",
152 	"sockb.so_snd.sb_wat",
153 	"tcpcb.last_ack_sent",
154 	"tcpcb.max_sndwnd",
155 	"tcpcb.rcv_adv",
156 	"tcpcb.rcv_nxt",
157 	"tcpcb.rcv_scale",
158 	"tcpcb.rcv_wnd",
159 	"tcpcb.rfbuf_cnt",
160 	"tcpcb.rfbuf_ts",
161 	"tcpcb.snd_cwnd",
162 	"tcpcb.snd_max",
163 	"tcpcb.snd_nxt",
164 	"tcpcb.snd_scale",
165 	"tcpcb.snd_ssthresh",
166 	"tcpcb.snd_una",
167 	"tcpcb.snd_wl1",
168 	"tcpcb.snd_wl2",
169 	"tcpcb.snd_wnd",
170 	"tcpcb.t_rcvtime",
171 	"tcpcb.t_rtseq",
172 	"tcpcb.t_rttmin",
173 	"tcpcb.t_rtttime",
174 	"tcpcb.t_rttvar",
175 	"tcpcb.t_srtt",
176 	"tcpcb.ts_recent",
177 	"tcpcb.ts_recent_age",
178 	NULL
179 };
180 
181 TAILQ_HEAD(, statctx) sc_queue;
182 
183 static void __dead
184 usage(void)
185 {
186 	fprintf(stderr,
187 	    "usage: tcpbench -l\n"
188 	    "       tcpbench [-46RUuv] [-B buf] [-b addr] [-k kvars] [-n connections]\n"
189 	    "                [-p port] [-r interval] [-S space] [-T toskeyword]\n"
190 	    "                [-t secs] [-V rtable] hostname\n"
191 	    "       tcpbench -s [-46Uuv] [-B buf] [-k kvars] [-p port] [-r interval]\n"
192 	    "                [-S space] [-T toskeyword] [-V rtable] [hostname]\n");
193 	exit(1);
194 }
195 
196 static void
197 signal_handler(int sig, short event, void *bula)
198 {
199 	/*
200 	 * signal handler rules don't apply, libevent decouples for us
201 	 */
202 	switch (sig) {
203 	case SIGINT:
204 	case SIGTERM:
205 	case SIGHUP:
206 		warnx("Terminated by signal %d", sig);
207 		exit(0);
208 		break;		/* NOTREACHED */
209 	default:
210 		errx(1, "unexpected signal %d", sig);
211 		break;		/* NOTREACHED */
212 	}
213 }
214 
215 static void
216 saddr_ntop(const struct sockaddr *addr, socklen_t alen, char *buf, size_t len)
217 {
218 	char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
219 	int herr;
220 
221 	if (addr->sa_family == AF_UNIX) {
222 		struct sockaddr_un *sun = (struct sockaddr_un *)addr;
223 		snprintf(buf, len, "%s", sun->sun_path);
224 		return;
225 	}
226 	if ((herr = getnameinfo(addr, alen, hbuf, sizeof(hbuf),
227 	    pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
228 		if (herr == EAI_SYSTEM)
229 			err(1, "getnameinfo");
230 		else
231 			errx(1, "getnameinfo: %s", gai_strerror(herr));
232 	}
233 	snprintf(buf, len, "[%s]:%s", hbuf, pbuf);
234 }
235 
236 static void
237 drop_gid(void)
238 {
239 	gid_t gid;
240 
241 	gid = getgid();
242 	if (setresgid(gid, gid, gid) == -1)
243 		err(1, "setresgid");
244 }
245 
246 static void
247 set_slice_timer(int on)
248 {
249 	struct timeval tv;
250 
251 	if (ptb->rflag == 0)
252 		return;
253 
254 	if (on) {
255 		if (evtimer_pending(&mainstats.timer, NULL))
256 			return;
257 		/* XXX Is there a better way to do this ? */
258 		tv.tv_sec = ptb->rflag / 1000;
259 		tv.tv_usec = (ptb->rflag % 1000) * 1000;
260 
261 		evtimer_add(&mainstats.timer, &tv);
262 	} else if (evtimer_pending(&mainstats.timer, NULL))
263 		evtimer_del(&mainstats.timer);
264 }
265 
266 static int
267 clock_gettime_tv(clockid_t clock_id, struct timeval *tv)
268 {
269 	struct timespec ts;
270 
271 	if (clock_gettime(clock_id, &ts) == -1)
272 		return (-1);
273 
274 	TIMESPEC_TO_TIMEVAL(tv, &ts);
275 
276 	return (0);
277 }
278 
279 static void
280 print_tcp_header(void)
281 {
282 	char **kv;
283 
284 	if (ptb->rflag == 0)
285 		return;
286 
287 	printf("%12s %14s %12s %8s ", "elapsed_ms", "bytes", "mbps",
288 	    "bwidth");
289 	for (kv = ptb->kvars;  ptb->kvars != NULL && *kv != NULL; kv++)
290 		printf("%s%s", kv != ptb->kvars ? "," : "", *kv);
291 	printf("\n");
292 }
293 
294 static void
295 kget(u_long addr, void *buf, size_t size)
296 {
297 	if (kvm_read(ptb->kvmh, addr, buf, size) != (ssize_t)size)
298 		errx(1, "kvm_read: %s", kvm_geterr(ptb->kvmh));
299 }
300 
301 static u_long
302 kfind_tcb(int sock)
303 {
304 	struct inpcbtable tcbtab;
305 	struct inpcb *next, *prev;
306 	struct inpcb inpcb, prevpcb;
307 	struct tcpcb tcpcb;
308 
309 	struct sockaddr_storage me, them;
310 	socklen_t melen, themlen;
311 	struct sockaddr_in *in4;
312 	struct sockaddr_in6 *in6;
313 	char tmp1[64], tmp2[64];
314 	int nretry;
315 
316 	nretry = 10;
317 	melen = themlen = sizeof(struct sockaddr_storage);
318 	if (getsockname(sock, (struct sockaddr *)&me, &melen) == -1)
319 		err(1, "getsockname");
320 	if (getpeername(sock, (struct sockaddr *)&them, &themlen) == -1)
321 		err(1, "getpeername");
322 	if (me.ss_family != them.ss_family)
323 		errx(1, "%s: me.ss_family != them.ss_family", __func__);
324 	if (me.ss_family != AF_INET && me.ss_family != AF_INET6)
325 		errx(1, "%s: unknown socket family", __func__);
326 	if (ptb->vflag >= 2) {
327 		saddr_ntop((struct sockaddr *)&me, me.ss_len,
328 		    tmp1, sizeof(tmp1));
329 		saddr_ntop((struct sockaddr *)&them, them.ss_len,
330 		    tmp2, sizeof(tmp2));
331 		fprintf(stderr, "Our socket local %s remote %s\n", tmp1, tmp2);
332 	}
333 	if (ptb->vflag >= 2)
334 		fprintf(stderr, "Using PCB table at %lu\n", ptb->ktcbtab);
335 retry:
336 	kget(ptb->ktcbtab, &tcbtab, sizeof(tcbtab));
337 	prev = NULL;
338 	next = TAILQ_FIRST(&tcbtab.inpt_queue);
339 
340 	if (ptb->vflag >= 2)
341 		fprintf(stderr, "PCB start at %p\n", next);
342 	while (next != NULL) {
343 		if (ptb->vflag >= 2)
344 			fprintf(stderr, "Checking PCB %p\n", next);
345 		kget((u_long)next, &inpcb, sizeof(inpcb));
346 		if (prev != NULL) {
347 			kget((u_long)prev, &prevpcb, sizeof(prevpcb));
348 			if (TAILQ_NEXT(&prevpcb, inp_queue) != next) {
349 				if (nretry--) {
350 					warnx("PCB prev pointer insane");
351 					goto retry;
352 				} else
353 					errx(1, "PCB prev pointer insane,"
354 					    " all attempts exhaused");
355 			}
356 		}
357 		prev = next;
358 		next = TAILQ_NEXT(&inpcb, inp_queue);
359 
360 		if (me.ss_family == AF_INET) {
361 			if ((inpcb.inp_flags & INP_IPV6) != 0) {
362 				if (ptb->vflag >= 2)
363 					fprintf(stderr, "Skip: INP_IPV6");
364 				continue;
365 			}
366 			if (ptb->vflag >= 2) {
367 				inet_ntop(AF_INET, &inpcb.inp_laddr,
368 				    tmp1, sizeof(tmp1));
369 				inet_ntop(AF_INET, &inpcb.inp_faddr,
370 				    tmp2, sizeof(tmp2));
371 				fprintf(stderr, "PCB %p local: [%s]:%d "
372 				    "remote: [%s]:%d\n", prev,
373 				    tmp1, inpcb.inp_lport,
374 				    tmp2, inpcb.inp_fport);
375 			}
376 			in4 = (struct sockaddr_in *)&me;
377 			if (memcmp(&in4->sin_addr, &inpcb.inp_laddr,
378 			    sizeof(struct in_addr)) != 0 ||
379 			    in4->sin_port != inpcb.inp_lport)
380 				continue;
381 			in4 = (struct sockaddr_in *)&them;
382 			if (memcmp(&in4->sin_addr, &inpcb.inp_faddr,
383 			    sizeof(struct in_addr)) != 0 ||
384 			    in4->sin_port != inpcb.inp_fport)
385 				continue;
386 		} else {
387 			if ((inpcb.inp_flags & INP_IPV6) == 0)
388 				continue;
389 			if (ptb->vflag >= 2) {
390 				inet_ntop(AF_INET6, &inpcb.inp_laddr6,
391 				    tmp1, sizeof(tmp1));
392 				inet_ntop(AF_INET6, &inpcb.inp_faddr6,
393 				    tmp2, sizeof(tmp2));
394 				fprintf(stderr, "PCB %p local: [%s]:%d "
395 				    "remote: [%s]:%d\n", prev,
396 				    tmp1, inpcb.inp_lport,
397 				    tmp2, inpcb.inp_fport);
398 			}
399 			in6 = (struct sockaddr_in6 *)&me;
400 			if (memcmp(&in6->sin6_addr, &inpcb.inp_laddr6,
401 			    sizeof(struct in6_addr)) != 0 ||
402 			    in6->sin6_port != inpcb.inp_lport)
403 				continue;
404 			in6 = (struct sockaddr_in6 *)&them;
405 			if (memcmp(&in6->sin6_addr, &inpcb.inp_faddr6,
406 			    sizeof(struct in6_addr)) != 0 ||
407 			    in6->sin6_port != inpcb.inp_fport)
408 				continue;
409 		}
410 		kget((u_long)inpcb.inp_ppcb, &tcpcb, sizeof(tcpcb));
411 		if (tcpcb.t_state != TCPS_ESTABLISHED) {
412 			if (ptb->vflag >= 2)
413 				fprintf(stderr, "Not established\n");
414 			continue;
415 		}
416 		if (ptb->vflag >= 2)
417 			fprintf(stderr, "Found PCB at %p\n", prev);
418 		return ((u_long)prev);
419 	}
420 
421 	errx(1, "No matching PCB found");
422 }
423 
424 static void
425 kupdate_stats(u_long tcbaddr, struct inpcb *inpcb,
426     struct tcpcb *tcpcb, struct socket *sockb)
427 {
428 	kget(tcbaddr, inpcb, sizeof(*inpcb));
429 	kget((u_long)inpcb->inp_ppcb, tcpcb, sizeof(*tcpcb));
430 	kget((u_long)inpcb->inp_socket, sockb, sizeof(*sockb));
431 }
432 
433 static void
434 check_kvar(const char *var)
435 {
436 	u_int i;
437 
438 	for (i = 0; allowed_kvars[i] != NULL; i++)
439 		if (strcmp(allowed_kvars[i], var) == 0)
440 			return;
441 	errx(1, "Unrecognised kvar: %s", var);
442 }
443 
444 static void
445 list_kvars(void)
446 {
447 	u_int i;
448 
449 	printf("Supported kernel variables:\n");
450 	for (i = 0; allowed_kvars[i] != NULL; i++)
451 		printf("\t%s\n", allowed_kvars[i]);
452 }
453 
454 static char **
455 check_prepare_kvars(char *list)
456 {
457 	char *item, **ret = NULL;
458 	u_int n = 0;
459 
460 	while ((item = strsep(&list, ", \t\n")) != NULL) {
461 		check_kvar(item);
462 		if ((ret = reallocarray(ret, (++n + 1), sizeof(*ret))) == NULL)
463 			err(1, "reallocarray(kvars)");
464 		if ((ret[n - 1] = strdup(item)) == NULL)
465 			err(1, "strdup");
466 		ret[n] = NULL;
467 	}
468 	return (ret);
469 }
470 
471 static void
472 stats_prepare(struct statctx *sc)
473 {
474 	sc->buf = ptb->dummybuf;
475 	sc->buflen = ptb->dummybuf_len;
476 
477 	if (ptb->kvars)
478 		sc->tcp_tcbaddr = kfind_tcb(sc->fd);
479 	if (clock_gettime_tv(CLOCK_MONOTONIC, &sc->t_start) == -1)
480 		err(1, "clock_gettime_tv");
481 	sc->t_last = sc->t_start;
482 
483 }
484 
485 static void
486 tcp_stats_display(unsigned long long total_elapsed, long double mbps,
487     float bwperc, struct statctx *sc, struct inpcb *inpcb,
488     struct tcpcb *tcpcb, struct socket *sockb)
489 {
490 	int j;
491 
492 	printf("%12llu %14llu %12.3Lf %7.2f%% ", total_elapsed, sc->bytes,
493 	    mbps, bwperc);
494 
495 	if (ptb->kvars != NULL) {
496 		kupdate_stats(sc->tcp_tcbaddr, inpcb, tcpcb,
497 		    sockb);
498 
499 		for (j = 0; ptb->kvars[j] != NULL; j++) {
500 #define S(a) #a
501 #define P(b, v, f)							\
502 			if (strcmp(ptb->kvars[j], S(b.v)) == 0) {	\
503 				printf("%s"f, j > 0 ? "," : "", b->v);	\
504 				continue;				\
505 			}
506 			P(inpcb, inp_flags, "0x%08x")
507 			P(sockb, so_rcv.sb_cc, "%lu")
508 			P(sockb, so_rcv.sb_hiwat, "%lu")
509 			P(sockb, so_rcv.sb_wat, "%lu")
510 			P(sockb, so_snd.sb_cc, "%lu")
511 			P(sockb, so_snd.sb_hiwat, "%lu")
512 			P(sockb, so_snd.sb_wat, "%lu")
513 			P(tcpcb, last_ack_sent, "%u")
514 			P(tcpcb, max_sndwnd, "%lu")
515 			P(tcpcb, rcv_adv, "%u")
516 			P(tcpcb, rcv_nxt, "%u")
517 			P(tcpcb, rcv_scale, "%u")
518 			P(tcpcb, rcv_wnd, "%lu")
519 			P(tcpcb, rfbuf_cnt, "%u")
520 			P(tcpcb, rfbuf_ts, "%u")
521 			P(tcpcb, snd_cwnd, "%lu")
522 			P(tcpcb, snd_max, "%u")
523 			P(tcpcb, snd_nxt, "%u")
524 			P(tcpcb, snd_scale, "%u")
525 			P(tcpcb, snd_ssthresh, "%lu")
526 			P(tcpcb, snd_una, "%u")
527 			P(tcpcb, snd_wl1, "%u")
528 			P(tcpcb, snd_wl2, "%u")
529 			P(tcpcb, snd_wnd, "%lu")
530 			P(tcpcb, t_rcvtime, "%u")
531 			P(tcpcb, t_rtseq, "%u")
532 			P(tcpcb, t_rttmin, "%hu")
533 			P(tcpcb, t_rtttime, "%u")
534 			P(tcpcb, t_rttvar, "%hu")
535 			P(tcpcb, t_srtt, "%hu")
536 			P(tcpcb, ts_recent, "%u")
537 			P(tcpcb, ts_recent_age, "%u")
538 #undef S
539 #undef P
540 		}
541 	}
542 	printf("\n");
543 }
544 
545 static void
546 tcp_process_slice(int fd, short event, void *bula)
547 {
548 	unsigned long long total_elapsed, since_last;
549 	long double mbps, slice_mbps = 0;
550 	float bwperc;
551 	struct statctx *sc;
552 	struct timeval t_cur, t_diff;
553 	struct inpcb inpcb;
554 	struct tcpcb tcpcb;
555 	struct socket sockb;
556 
557 	TAILQ_FOREACH(sc, &sc_queue, entry) {
558 		if (clock_gettime_tv(CLOCK_MONOTONIC, &t_cur) == -1)
559 			err(1, "clock_gettime_tv");
560 		if (ptb->kvars != NULL) /* process kernel stats */
561 			kupdate_stats(sc->tcp_tcbaddr, &inpcb, &tcpcb,
562 			    &sockb);
563 
564 		timersub(&t_cur, &sc->t_start, &t_diff);
565 		total_elapsed = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000;
566 		timersub(&t_cur, &sc->t_last, &t_diff);
567 		since_last = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000;
568 		bwperc = (sc->bytes * 100.0) / mainstats.slice_bytes;
569 		mbps = (sc->bytes * 8) / (since_last * 1000.0);
570 		slice_mbps += mbps;
571 
572 		tcp_stats_display(total_elapsed, mbps, bwperc, sc,
573 		    &inpcb, &tcpcb, &sockb);
574 
575 		sc->t_last = t_cur;
576 		sc->bytes = 0;
577 	}
578 
579 	/* process stats for this slice */
580 	if (slice_mbps > mainstats.peak_mbps)
581 		mainstats.peak_mbps = slice_mbps;
582 	printf("Conn: %3d Mbps: %12.3Lf Peak Mbps: %12.3Lf Avg Mbps: %12.3Lf\n",
583 	    mainstats.nconns, slice_mbps, mainstats.peak_mbps,
584 	    mainstats.nconns ? slice_mbps / mainstats.nconns : 0);
585 	mainstats.slice_bytes = 0;
586 
587 	set_slice_timer(mainstats.nconns > 0);
588 }
589 
590 static void
591 udp_process_slice(int fd, short event, void *v_sc)
592 {
593 	struct statctx *sc = v_sc;
594 	unsigned long long total_elapsed, since_last, pps;
595 	long double slice_mbps;
596 	struct timeval t_cur, t_diff;
597 
598 	if (clock_gettime_tv(CLOCK_MONOTONIC, &t_cur) == -1)
599 		err(1, "clock_gettime_tv");
600 	/* Calculate pps */
601 	timersub(&t_cur, &sc->t_start, &t_diff);
602 	total_elapsed = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000;
603 	timersub(&t_cur, &sc->t_last, &t_diff);
604 	since_last = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000;
605 	slice_mbps = (sc->bytes * 8) / (since_last * 1000.0);
606 	pps = (sc->udp_slice_pkts * 1000) / since_last;
607 	if (slice_mbps > mainstats.peak_mbps)
608 		mainstats.peak_mbps = slice_mbps;
609 	printf("Elapsed: %11llu Mbps: %11.3Lf Peak Mbps: %11.3Lf %s PPS: %7llu\n",
610 	    total_elapsed, slice_mbps, mainstats.peak_mbps,
611 	    ptb->sflag ? "Rx" : "Tx", pps);
612 
613 	/* Clean up this slice time */
614 	sc->t_last = t_cur;
615 	sc->bytes = 0;
616 	sc->udp_slice_pkts = 0;
617 	set_slice_timer(1);
618 }
619 
620 static void
621 udp_server_handle_sc(int fd, short event, void *v_sc)
622 {
623 	ssize_t n;
624 	struct statctx *sc = v_sc;
625 
626 	n = read(fd, ptb->dummybuf, ptb->dummybuf_len);
627 	if (n == 0)
628 		return;
629 	else if (n == -1) {
630 		if (errno != EINTR && errno != EWOULDBLOCK)
631 			warn("fd %d read error", fd);
632 		return;
633 	}
634 
635 	if (ptb->vflag >= 3)
636 		fprintf(stderr, "read: %zd bytes\n", n);
637 	/* If this was our first packet, start slice timer */
638 	if (mainstats.peak_mbps == 0)
639 		set_slice_timer(1);
640 	/* Account packet */
641 	sc->udp_slice_pkts++;
642 	sc->bytes += n;
643 }
644 
645 static void
646 tcp_server_handle_sc(int fd, short event, void *v_sc)
647 {
648 	struct statctx *sc = v_sc;
649 	ssize_t n;
650 
651 	n = read(sc->fd, sc->buf, sc->buflen);
652 	if (n == -1) {
653 		if (errno != EINTR && errno != EWOULDBLOCK)
654 			warn("fd %d read error", sc->fd);
655 		return;
656 	} else if (n == 0) {
657 		if (ptb->vflag)
658 			fprintf(stderr, "%8d closed by remote end\n", sc->fd);
659 
660 		TAILQ_REMOVE(&sc_queue, sc, entry);
661 
662 		event_del(&sc->ev);
663 		close(sc->fd);
664 
665 		/* Some file descriptors are available again. */
666 		if (evtimer_pending(&sc->tcp_ts->evt, NULL)) {
667 			evtimer_del(&sc->tcp_ts->evt);
668 			event_add(&sc->tcp_ts->ev, NULL);
669 		}
670 
671 		free(sc);
672 		mainstats.nconns--;
673 		return;
674 	}
675 	if (ptb->vflag >= 3)
676 		fprintf(stderr, "read: %zd bytes\n", n);
677 	sc->bytes += n;
678 	mainstats.slice_bytes += n;
679 }
680 
681 static void
682 tcp_server_accept(int fd, short event, void *arg)
683 {
684 	struct tcpservsock *ts = arg;
685 	int sock;
686 	struct statctx *sc;
687 	struct sockaddr_storage ss;
688 	socklen_t sslen;
689 	char tmp[128];
690 
691 	sslen = sizeof(ss);
692 
693 	event_add(&ts->ev, NULL);
694 	if (event & EV_TIMEOUT)
695 		return;
696 	if ((sock = accept4(fd, (struct sockaddr *)&ss, &sslen, SOCK_NONBLOCK))
697 	    == -1) {
698 		/*
699 		 * Pause accept if we are out of file descriptors, or
700 		 * libevent will haunt us here too.
701 		 */
702 		if (errno == ENFILE || errno == EMFILE) {
703 			struct timeval evtpause = { 1, 0 };
704 
705 			event_del(&ts->ev);
706 			evtimer_add(&ts->evt, &evtpause);
707 		} else if (errno != EWOULDBLOCK && errno != EINTR &&
708 		    errno != ECONNABORTED)
709 			warn("accept");
710 		return;
711 	}
712 	saddr_ntop((struct sockaddr *)&ss, sslen,
713 	    tmp, sizeof(tmp));
714 	if (ptb->Tflag != -1 && ss.ss_family == AF_INET) {
715 		if (setsockopt(sock, IPPROTO_IP, IP_TOS,
716 		    &ptb->Tflag, sizeof(ptb->Tflag)))
717 			err(1, "setsockopt IP_TOS");
718 	}
719 	if (ptb->Tflag != -1 && ss.ss_family == AF_INET6) {
720 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS,
721 		    &ptb->Tflag, sizeof(ptb->Tflag)))
722 			err(1, "setsockopt IPV6_TCLASS");
723 	}
724 	/* Alloc client structure and register reading callback */
725 	if ((sc = calloc(1, sizeof(*sc))) == NULL)
726 		err(1, "calloc");
727 	sc->tcp_ts = ts;
728 	sc->fd = sock;
729 	stats_prepare(sc);
730 	event_set(&sc->ev, sc->fd, EV_READ | EV_PERSIST,
731 	    tcp_server_handle_sc, sc);
732 	event_add(&sc->ev, NULL);
733 	TAILQ_INSERT_TAIL(&sc_queue, sc, entry);
734 	mainstats.nconns++;
735 	if (mainstats.nconns == 1)
736 		set_slice_timer(1);
737 	if (ptb->vflag)
738 		fprintf(stderr, "Accepted connection from %s, fd = %d\n",
739 		    tmp, sc->fd);
740 }
741 
742 static void
743 server_init(struct addrinfo *aitop, struct statctx *udp_sc)
744 {
745 	char tmp[128];
746 	int sock, on = 1;
747 	struct addrinfo *ai;
748 	struct event *ev;
749 	struct tcpservsock *ts;
750 	nfds_t lnfds;
751 
752 	lnfds = 0;
753 	for (ai = aitop; ai != NULL; ai = ai->ai_next) {
754 		saddr_ntop(ai->ai_addr, ai->ai_addrlen, tmp, sizeof(tmp));
755 		if (ptb->vflag)
756 			fprintf(stderr, "Try to bind to %s\n", tmp);
757 		if ((sock = socket(ai->ai_family, ai->ai_socktype,
758 		    ai->ai_protocol)) == -1) {
759 			if (ai->ai_next == NULL)
760 				err(1, "socket");
761 			if (ptb->vflag)
762 				warn("socket");
763 			continue;
764 		}
765 		if (ptb->Tflag != -1 && ai->ai_family == AF_INET) {
766 			if (setsockopt(sock, IPPROTO_IP, IP_TOS,
767 			    &ptb->Tflag, sizeof(ptb->Tflag)))
768 				err(1, "setsockopt IP_TOS");
769 		}
770 		if (ptb->Tflag != -1 && ai->ai_family == AF_INET6) {
771 			if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS,
772 			    &ptb->Tflag, sizeof(ptb->Tflag)))
773 				err(1, "setsockopt IPV6_TCLASS");
774 		}
775 		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
776 		    &on, sizeof(on)) == -1)
777 			warn("reuse port");
778 		if (bind(sock, ai->ai_addr, ai->ai_addrlen) != 0) {
779 			if (ai->ai_next == NULL)
780 				err(1, "bind");
781 			if (ptb->vflag)
782 				warn("bind");
783 			close(sock);
784 			continue;
785 		}
786 		if (ptb->Sflag) {
787 			if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
788 			    &ptb->Sflag, sizeof(ptb->Sflag)) == -1)
789 				warn("set receive socket buffer size");
790 		}
791 		if (TCP_MODE) {
792 			if (listen(sock, 64) == -1) {
793 				if (ai->ai_next == NULL)
794 					err(1, "listen");
795 				if (ptb->vflag)
796 					warn("listen");
797 				close(sock);
798 				continue;
799 			}
800 		}
801 		if (UDP_MODE) {
802 			if ((ev = calloc(1, sizeof(*ev))) == NULL)
803 				err(1, "calloc");
804 			event_set(ev, sock, EV_READ | EV_PERSIST,
805 			    udp_server_handle_sc, udp_sc);
806 			event_add(ev, NULL);
807 		} else {
808 			if ((ts = calloc(1, sizeof(*ts))) == NULL)
809 				err(1, "calloc");
810 
811 			ts->fd = sock;
812 			evtimer_set(&ts->evt, tcp_server_accept, ts);
813 			event_set(&ts->ev, ts->fd, EV_READ,
814 			    tcp_server_accept, ts);
815 			event_add(&ts->ev, NULL);
816 		}
817 		if (ptb->vflag >= 3)
818 			fprintf(stderr, "bound to fd %d\n", sock);
819 		lnfds++;
820 	}
821 	if (!ptb->Uflag)
822 		freeaddrinfo(aitop);
823 	if (lnfds == 0)
824 		errx(1, "No working listen addresses found");
825 }
826 
827 static void
828 client_handle_sc(int fd, short event, void *v_sc)
829 {
830 	struct statctx *sc = v_sc;
831 	ssize_t n;
832 	size_t blen = sc->buflen;
833 
834 	if (ptb->Rflag)
835 		blen = arc4random_uniform(blen) + 1;
836 	if ((n = write(sc->fd, sc->buf, blen)) == -1) {
837 		if (errno == EINTR || errno == EWOULDBLOCK ||
838 		    (UDP_MODE && errno == ENOBUFS))
839 			return;
840 		err(1, "write");
841 	}
842 	if (TCP_MODE && n == 0) {
843 		fprintf(stderr, "Remote end closed connection");
844 		exit(1);
845 	}
846 	if (ptb->vflag >= 3)
847 		fprintf(stderr, "write: %zd bytes\n", n);
848 	sc->bytes += n;
849 	mainstats.slice_bytes += n;
850 	if (UDP_MODE)
851 		sc->udp_slice_pkts++;
852 }
853 
854 static void
855 client_init(struct addrinfo *aitop, int nconn, struct statctx *udp_sc,
856     struct addrinfo *aib)
857 {
858 	struct statctx *sc;
859 	struct addrinfo *ai;
860 	char tmp[128];
861 	int i, r, sock;
862 
863 	sc = udp_sc;
864 	for (i = 0; i < nconn; i++) {
865 		for (sock = -1, ai = aitop; ai != NULL; ai = ai->ai_next) {
866 			saddr_ntop(ai->ai_addr, ai->ai_addrlen, tmp,
867 			    sizeof(tmp));
868 			if (ptb->vflag && i == 0)
869 				fprintf(stderr, "Trying %s\n", tmp);
870 			if ((sock = socket(ai->ai_family, ai->ai_socktype,
871 			    ai->ai_protocol)) == -1) {
872 				if (ai->ai_next == NULL)
873 					err(1, "socket");
874 				if (ptb->vflag)
875 					warn("socket");
876 				continue;
877 			}
878 			if (aib != NULL) {
879 				saddr_ntop(aib->ai_addr, aib->ai_addrlen,
880 				    tmp, sizeof(tmp));
881 				if (ptb->vflag)
882 					fprintf(stderr,
883 					    "Try to bind to %s\n", tmp);
884 				if (bind(sock, (struct sockaddr *)aib->ai_addr,
885 				    aib->ai_addrlen) == -1)
886 					err(1, "bind");
887 			}
888 			if (ptb->Tflag != -1 && ai->ai_family == AF_INET) {
889 				if (setsockopt(sock, IPPROTO_IP, IP_TOS,
890 				    &ptb->Tflag, sizeof(ptb->Tflag)))
891 					err(1, "setsockopt IP_TOS");
892 			}
893 			if (ptb->Tflag != -1 && ai->ai_family == AF_INET6) {
894 				if (setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS,
895 				    &ptb->Tflag, sizeof(ptb->Tflag)))
896 					err(1, "setsockopt IPV6_TCLASS");
897 			}
898 			if (ptb->Sflag) {
899 				if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
900 				    &ptb->Sflag, sizeof(ptb->Sflag)) == -1)
901 					warn("set send socket buffer size");
902 			}
903 			if (connect(sock, ai->ai_addr, ai->ai_addrlen) != 0) {
904 				if (ai->ai_next == NULL)
905 					err(1, "connect");
906 				if (ptb->vflag)
907 					warn("connect");
908 				close(sock);
909 				sock = -1;
910 				continue;
911 			}
912 			break;
913 		}
914 		if (sock == -1)
915 			errx(1, "No host found");
916 		if ((r = fcntl(sock, F_GETFL)) == -1)
917 			err(1, "fcntl(F_GETFL)");
918 		r |= O_NONBLOCK;
919 		if (fcntl(sock, F_SETFL, r) == -1)
920 			err(1, "fcntl(F_SETFL, O_NONBLOCK)");
921 		/* Alloc and prepare stats */
922 		if (TCP_MODE) {
923 			if ((sc = calloc(1, sizeof(*sc))) == NULL)
924 				err(1, "calloc");
925 		}
926 		sc->fd = sock;
927 		stats_prepare(sc);
928 		event_set(&sc->ev, sc->fd, EV_WRITE | EV_PERSIST,
929 		    client_handle_sc, sc);
930 		event_add(&sc->ev, NULL);
931 		TAILQ_INSERT_TAIL(&sc_queue, sc, entry);
932 		mainstats.nconns++;
933 		if (mainstats.nconns == 1)
934 			set_slice_timer(1);
935 	}
936 	if (!ptb->Uflag)
937 		freeaddrinfo(aitop);
938 	if (aib != NULL)
939 		freeaddrinfo(aib);
940 
941 	if (ptb->vflag && nconn > 1)
942 		fprintf(stderr, "%d connections established\n",
943 		    mainstats.nconns);
944 }
945 
946 static int
947 map_tos(char *s, int *val)
948 {
949 	/* DiffServ Codepoints and other TOS mappings */
950 	const struct toskeywords {
951 		const char	*keyword;
952 		int		 val;
953 	} *t, toskeywords[] = {
954 		{ "af11",		IPTOS_DSCP_AF11 },
955 		{ "af12",		IPTOS_DSCP_AF12 },
956 		{ "af13",		IPTOS_DSCP_AF13 },
957 		{ "af21",		IPTOS_DSCP_AF21 },
958 		{ "af22",		IPTOS_DSCP_AF22 },
959 		{ "af23",		IPTOS_DSCP_AF23 },
960 		{ "af31",		IPTOS_DSCP_AF31 },
961 		{ "af32",		IPTOS_DSCP_AF32 },
962 		{ "af33",		IPTOS_DSCP_AF33 },
963 		{ "af41",		IPTOS_DSCP_AF41 },
964 		{ "af42",		IPTOS_DSCP_AF42 },
965 		{ "af43",		IPTOS_DSCP_AF43 },
966 		{ "critical",		IPTOS_PREC_CRITIC_ECP },
967 		{ "cs0",		IPTOS_DSCP_CS0 },
968 		{ "cs1",		IPTOS_DSCP_CS1 },
969 		{ "cs2",		IPTOS_DSCP_CS2 },
970 		{ "cs3",		IPTOS_DSCP_CS3 },
971 		{ "cs4",		IPTOS_DSCP_CS4 },
972 		{ "cs5",		IPTOS_DSCP_CS5 },
973 		{ "cs6",		IPTOS_DSCP_CS6 },
974 		{ "cs7",		IPTOS_DSCP_CS7 },
975 		{ "ef",			IPTOS_DSCP_EF },
976 		{ "inetcontrol",	IPTOS_PREC_INTERNETCONTROL },
977 		{ "lowdelay",		IPTOS_LOWDELAY },
978 		{ "netcontrol",		IPTOS_PREC_NETCONTROL },
979 		{ "reliability",	IPTOS_RELIABILITY },
980 		{ "throughput",		IPTOS_THROUGHPUT },
981 		{ NULL,			-1 },
982 	};
983 
984 	for (t = toskeywords; t->keyword != NULL; t++) {
985 		if (strcmp(s, t->keyword) == 0) {
986 			*val = t->val;
987 			return (1);
988 		}
989 	}
990 
991 	return (0);
992 }
993 
994 static void
995 quit(int sig, short event, void *arg)
996 {
997 	exit(0);
998 }
999 
1000 int
1001 main(int argc, char **argv)
1002 {
1003 	struct timeval tv;
1004 	unsigned int secs, rtable;
1005 
1006 	char kerr[_POSIX2_LINE_MAX], *tmp;
1007 	struct addrinfo *aitop, *aib, hints;
1008 	const char *errstr;
1009 	struct rlimit rl;
1010 	int ch, herr, nconn;
1011 	int family = PF_UNSPEC;
1012 	struct nlist nl[] = { { "_tcbtable" }, { "" } };
1013 	const char *host = NULL, *port = DEFAULT_PORT, *srcbind = NULL;
1014 	struct event ev_sigint, ev_sigterm, ev_sighup, ev_progtimer;
1015 	struct statctx *udp_sc = NULL;
1016 	struct sockaddr_un sock_un;
1017 
1018 	/* Init world */
1019 	setvbuf(stdout, NULL, _IOLBF, 0);
1020 	ptb = &tcpbench;
1021 	ptb->dummybuf_len = 0;
1022 	ptb->Sflag = ptb->sflag = ptb->vflag = ptb->Rflag = ptb->Uflag = 0;
1023 	ptb->kvmh  = NULL;
1024 	ptb->kvars = NULL;
1025 	ptb->rflag = DEFAULT_STATS_INTERVAL;
1026 	ptb->Tflag = -1;
1027 	nconn = 1;
1028 	aib = NULL;
1029 	secs = 0;
1030 
1031 	while ((ch = getopt(argc, argv, "46b:B:hlk:n:p:Rr:sS:t:T:uUvV:")) != -1) {
1032 		switch (ch) {
1033 		case '4':
1034 			family = PF_INET;
1035 			break;
1036 		case '6':
1037 			family = PF_INET6;
1038 			break;
1039 		case 'b':
1040 			srcbind = optarg;
1041 			break;
1042 		case 'l':
1043 			list_kvars();
1044 			exit(0);
1045 		case 'k':
1046 			if ((tmp = strdup(optarg)) == NULL)
1047 				err(1, "strdup");
1048 			ptb->kvars = check_prepare_kvars(tmp);
1049 			free(tmp);
1050 			break;
1051 		case 'R':
1052 			ptb->Rflag = 1;
1053 			break;
1054 		case 'r':
1055 			ptb->rflag = strtonum(optarg, 0, 60 * 60 * 24 * 1000,
1056 			    &errstr);
1057 			if (errstr != NULL)
1058 				errx(1, "statistics interval is %s: %s",
1059 				    errstr, optarg);
1060 			break;
1061 		case 'p':
1062 			port = optarg;
1063 			break;
1064 		case 's':
1065 			ptb->sflag = 1;
1066 			break;
1067 		case 'S':
1068 			ptb->Sflag = strtonum(optarg, 0, 1024*1024*1024,
1069 			    &errstr);
1070 			if (errstr != NULL)
1071 				errx(1, "socket buffer size is %s: %s",
1072 				    errstr, optarg);
1073 			break;
1074 		case 'B':
1075 			ptb->dummybuf_len = strtonum(optarg, 0, 1024*1024*1024,
1076 			    &errstr);
1077 			if (errstr != NULL)
1078 				errx(1, "read/write buffer size is %s: %s",
1079 				    errstr, optarg);
1080 			break;
1081 		case 'v':
1082 			ptb->vflag++;
1083 			break;
1084 		case 'V':
1085 			rtable = (unsigned int)strtonum(optarg, 0,
1086 			    RT_TABLEID_MAX, &errstr);
1087 			if (errstr)
1088 				errx(1, "rtable value is %s: %s",
1089 				    errstr, optarg);
1090 			if (setrtable(rtable) == -1)
1091 				err(1, "setrtable");
1092 			break;
1093 		case 'n':
1094 			nconn = strtonum(optarg, 0, 65535, &errstr);
1095 			if (errstr != NULL)
1096 				errx(1, "number of connections is %s: %s",
1097 				    errstr, optarg);
1098 			break;
1099 		case 'u':
1100 			ptb->uflag = 1;
1101 			break;
1102 		case 'U':
1103 			ptb->Uflag = 1;
1104 			break;
1105 		case 'T':
1106 			if (map_tos(optarg, &ptb->Tflag))
1107 				break;
1108 			errstr = NULL;
1109 			if (strlen(optarg) > 1 && optarg[0] == '0' &&
1110 			    optarg[1] == 'x')
1111 				ptb->Tflag = (int)strtol(optarg, NULL, 16);
1112 			else
1113 				ptb->Tflag = (int)strtonum(optarg, 0, 255,
1114 				    &errstr);
1115 			if (ptb->Tflag == -1 || ptb->Tflag > 255 || errstr)
1116 				errx(1, "illegal tos value %s", optarg);
1117 			break;
1118 		case 't':
1119 			secs = strtonum(optarg, 1, UINT_MAX, &errstr);
1120 			if (errstr != NULL)
1121 				errx(1, "secs is %s: %s",
1122 				    errstr, optarg);
1123 			break;
1124 		case 'h':
1125 		default:
1126 			usage();
1127 		}
1128 	}
1129 
1130 	if (pledge("stdio unveil rpath dns inet unix id proc", NULL) == -1)
1131 		err(1, "pledge");
1132 
1133 	argv += optind;
1134 	argc -= optind;
1135 	if ((argc != (ptb->sflag && !ptb->Uflag ? 0 : 1)) ||
1136 	    (UDP_MODE && (ptb->kvars || nconn != 1)))
1137 		usage();
1138 
1139 	if (ptb->kvars) {
1140 		if (unveil(_PATH_MEM, "r") == -1)
1141 			err(1, "unveil");
1142 		if (unveil(_PATH_KMEM, "r") == -1)
1143 			err(1, "unveil");
1144 		if (unveil(_PATH_KSYMS, "r") == -1)
1145 			err(1, "unveil");
1146 
1147 		if ((ptb->kvmh = kvm_openfiles(NULL, NULL, NULL,
1148 		    O_RDONLY, kerr)) == NULL)
1149 			errx(1, "kvm_open: %s", kerr);
1150 		drop_gid();
1151 		if (kvm_nlist(ptb->kvmh, nl) < 0 || nl[0].n_type == 0)
1152 			errx(1, "kvm: no namelist");
1153 		ptb->ktcbtab = nl[0].n_value;
1154 	} else
1155 		drop_gid();
1156 
1157 	if (!ptb->sflag || ptb->Uflag)
1158 		host = argv[0];
1159 
1160 	if (ptb->Uflag)
1161 		if (unveil(host, "rwc") == -1)
1162 			err(1, "unveil");
1163 
1164 	if (pledge("stdio id dns inet unix", NULL) == -1)
1165 		err(1, "pledge");
1166 
1167 	/*
1168 	 * Rationale,
1169 	 * If TCP, use a big buffer with big reads/writes.
1170 	 * If UDP, use a big buffer in server and a buffer the size of a
1171 	 * ethernet packet.
1172 	 */
1173 	if (!ptb->dummybuf_len) {
1174 		if (ptb->sflag || TCP_MODE)
1175 			ptb->dummybuf_len = DEFAULT_BUF;
1176 		else
1177 			ptb->dummybuf_len = DEFAULT_UDP_PKT;
1178 	}
1179 
1180 	bzero(&hints, sizeof(hints));
1181 	hints.ai_family = family;
1182 	if (UDP_MODE) {
1183 		hints.ai_socktype = SOCK_DGRAM;
1184 		hints.ai_protocol = IPPROTO_UDP;
1185 	} else {
1186 		hints.ai_socktype = SOCK_STREAM;
1187 		hints.ai_protocol = IPPROTO_TCP;
1188 	}
1189 	if (ptb->Uflag) {
1190 		hints.ai_family = AF_UNIX;
1191 		hints.ai_protocol = 0;
1192 		sock_un.sun_family = AF_UNIX;
1193 		if (strlcpy(sock_un.sun_path, host, sizeof(sock_un.sun_path)) >=
1194 		    sizeof(sock_un.sun_path))
1195 			errx(1, "socket name '%s' too long", host);
1196 		hints.ai_addr = (struct sockaddr *)&sock_un;
1197 		hints.ai_addrlen = sizeof(sock_un);
1198 		aitop = &hints;
1199 	} else {
1200 		if (ptb->sflag)
1201 			hints.ai_flags = AI_PASSIVE;
1202 		if (srcbind != NULL) {
1203 			hints.ai_flags |= AI_NUMERICHOST;
1204 			herr = getaddrinfo(srcbind, NULL, &hints, &aib);
1205 			hints.ai_flags &= ~AI_NUMERICHOST;
1206 			if (herr != 0) {
1207 				if (herr == EAI_SYSTEM)
1208 					err(1, "getaddrinfo");
1209 				else
1210 					errx(1, "getaddrinfo: %s",
1211 					    gai_strerror(herr));
1212 			}
1213 		}
1214 		if ((herr = getaddrinfo(host, port, &hints, &aitop)) != 0) {
1215 			if (herr == EAI_SYSTEM)
1216 				err(1, "getaddrinfo");
1217 			else
1218 				errx(1, "getaddrinfo: %s", gai_strerror(herr));
1219 		}
1220 	}
1221 
1222 	if (pledge("stdio id inet unix", NULL) == -1)
1223 		err(1, "pledge");
1224 
1225 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
1226 		err(1, "getrlimit");
1227 	if (rl.rlim_cur < MAX_FD)
1228 		rl.rlim_cur = MAX_FD;
1229 	if (setrlimit(RLIMIT_NOFILE, &rl))
1230 		err(1, "setrlimit");
1231 	if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
1232 		err(1, "getrlimit");
1233 
1234 	if (pledge("stdio inet unix", NULL) == -1)
1235 		err(1, "pledge");
1236 
1237 	/* Init world */
1238 	TAILQ_INIT(&sc_queue);
1239 	if ((ptb->dummybuf = malloc(ptb->dummybuf_len)) == NULL)
1240 		err(1, "malloc");
1241 	arc4random_buf(ptb->dummybuf, ptb->dummybuf_len);
1242 
1243 	/* Setup libevent and signals */
1244 	event_init();
1245 	signal_set(&ev_sigterm, SIGTERM, signal_handler, NULL);
1246 	signal_set(&ev_sighup, SIGHUP, signal_handler, NULL);
1247 	signal_set(&ev_sigint, SIGINT, signal_handler, NULL);
1248 	signal_add(&ev_sigint, NULL);
1249 	signal_add(&ev_sigterm, NULL);
1250 	signal_add(&ev_sighup, NULL);
1251 	signal(SIGPIPE, SIG_IGN);
1252 
1253 	if (UDP_MODE) {
1254 		if ((udp_sc = calloc(1, sizeof(*udp_sc))) == NULL)
1255 			err(1, "calloc");
1256 		udp_sc->fd = -1;
1257 		stats_prepare(udp_sc);
1258 		evtimer_set(&mainstats.timer, udp_process_slice, udp_sc);
1259 	} else {
1260 		print_tcp_header();
1261 		evtimer_set(&mainstats.timer, tcp_process_slice, NULL);
1262 	}
1263 
1264 	if (ptb->sflag)
1265 		server_init(aitop, udp_sc);
1266 	else {
1267 		if (secs > 0) {
1268 			timerclear(&tv);
1269 			tv.tv_sec = secs + 1;
1270 			evtimer_set(&ev_progtimer, quit, NULL);
1271 			evtimer_add(&ev_progtimer, &tv);
1272 		}
1273 		client_init(aitop, nconn, udp_sc, aib);
1274 
1275 		if (pledge("stdio", NULL) == -1)
1276 			err(1, "pledge");
1277 	}
1278 
1279 	/* libevent main loop*/
1280 	event_dispatch();
1281 
1282 	return (0);
1283 }
1284