1 #include <sys/types.h>
2 #include <sys/mman.h>
3 #include <sys/socket.h>
4 #include <sys/time.h>
5 #include <sys/wait.h>
6 
7 #include <arpa/inet.h>
8 #include <netinet/in.h>
9 
10 #include <errno.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 static void	mainloop(const struct sockaddr_in *, long, u_long *);
18 
19 static int	global_stopped;
20 
21 static void
22 usage(const char *cmd)
23 {
24 	fprintf(stderr, "%s -4 inet4 -p port "
25 	    "[-i n_instance] [-l duration]\n", cmd);
26 	exit(1);
27 }
28 
29 int
30 main(int argc, char *argv[])
31 {
32 	struct sockaddr_in in;
33 	int opt, ninst, i;
34 	long dur;
35 	u_long *result, sum;
36 
37 	memset(&in, 0, sizeof(in));
38 	in.sin_family = AF_INET;
39 
40 	ninst = 1;
41 	dur = 10;
42 
43 	while ((opt = getopt(argc, argv, "4:p:i:l:")) != -1) {
44 		switch (opt) {
45 		case '4':
46 			if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) {
47 				fprintf(stderr, "invalid inet address %s\n",
48 				    optarg);
49 				usage(argv[0]);
50 			}
51 			break;
52 
53 		case 'p':
54 			in.sin_port = htons(atoi(optarg));
55 			break;
56 
57 		case 'i':
58 			ninst = atoi(optarg);
59 			break;
60 
61 		case 'l':
62 			dur = strtol(optarg, NULL, 10);
63 			break;
64 
65 		default:
66 			usage(argv[0]);
67 		}
68 	}
69 
70 	if (ninst < 1 || dur < 1 ||
71 	    in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY)
72 		usage(argv[0]);
73 
74 	result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE,
75 	    MAP_ANON | MAP_SHARED, -1, 0);
76 	if (result == MAP_FAILED) {
77 		fprintf(stderr, "mmap failed: %d\n", errno);
78 		exit(1);
79 	}
80 	memset(result, 0, ninst * sizeof(u_long));
81 
82 	for (i = 0; i < ninst; ++i) {
83 		pid_t pid;
84 
85 		pid = fork();
86 		if (pid == 0) {
87 			mainloop(&in, dur, &result[i]);
88 			exit(0);
89 		} else if (pid < 0) {
90 			fprintf(stderr, "fork failed: %d\n", errno);
91 		}
92 	}
93 
94 	for (i = 0; i < ninst; ++i) {
95 		pid_t pid;
96 
97 		pid = waitpid(-1, NULL, 0);
98 		if (pid < 0) {
99 			fprintf(stderr, "waitpid failed: %d\n", errno);
100 			exit(1);
101 		}
102 	}
103 
104 	sum = 0;
105 	for (i = 0; i < ninst; ++i)
106 		sum += result[i];
107 	printf("%.2f\n", (double)sum / (double)dur);
108 
109 	exit(0);
110 }
111 
112 static void
113 signal_handler(int signum __unused)
114 {
115 	global_stopped = 1;
116 }
117 
118 
119 static void
120 mainloop(const struct sockaddr_in *in, long dur, u_long *res)
121 {
122 	struct itimerval it;
123 	u_long count = 0;
124 
125 	if (signal(SIGALRM, signal_handler) == SIG_ERR) {
126 		fprintf(stderr, "signal failed: %d\n", errno);
127 		return;
128 	}
129 
130 	it.it_interval.tv_sec = 0;
131 	it.it_interval.tv_usec = 0;
132 	it.it_value.tv_sec = dur;
133 	it.it_value.tv_usec = 0;
134 
135 	if (setitimer(ITIMER_REAL, &it, NULL) < 0) {
136 		fprintf(stderr, "setitimer failed: %d\n", errno);
137 		return;
138 	}
139 
140 	while (!global_stopped) {
141 		int s;
142 
143 		s = socket(AF_INET, SOCK_STREAM, 0);
144 		if (s < 0)
145 			continue;
146 
147 		if (connect(s,
148 		    (const struct sockaddr *)in, sizeof(*in)) == 0)
149 			++count;
150 		close(s);
151 	}
152 	*res = count;
153 }
154