1*73610d44SSepherosa Ziehau #include <sys/types.h>
2*73610d44SSepherosa Ziehau #include <sys/socket.h>
3*73610d44SSepherosa Ziehau #include <sys/time.h>
4*73610d44SSepherosa Ziehau #include <sys/un.h>
5*73610d44SSepherosa Ziehau #include <sys/wait.h>
6*73610d44SSepherosa Ziehau 
7*73610d44SSepherosa Ziehau #include <arpa/inet.h>
8*73610d44SSepherosa Ziehau #include <netinet/in.h>
9*73610d44SSepherosa Ziehau 
10*73610d44SSepherosa Ziehau #include <err.h>
11*73610d44SSepherosa Ziehau #include <errno.h>
12*73610d44SSepherosa Ziehau #include <signal.h>
13*73610d44SSepherosa Ziehau #include <stdio.h>
14*73610d44SSepherosa Ziehau #include <stdlib.h>
15*73610d44SSepherosa Ziehau #include <string.h>
16*73610d44SSepherosa Ziehau #include <unistd.h>
17*73610d44SSepherosa Ziehau 
18*73610d44SSepherosa Ziehau #define WRITE_WAIT_TIME	8	/* unit: sec */
19*73610d44SSepherosa Ziehau #define READ_WAIT_MIN	6	/* unit: sec */
20*73610d44SSepherosa Ziehau 
21*73610d44SSepherosa Ziehau static void
usage(const char * cmd)22*73610d44SSepherosa Ziehau usage(const char *cmd)
23*73610d44SSepherosa Ziehau {
24*73610d44SSepherosa Ziehau 	fprintf(stderr, "%s -p port\n", cmd);
25*73610d44SSepherosa Ziehau 	exit(1);
26*73610d44SSepherosa Ziehau }
27*73610d44SSepherosa Ziehau 
28*73610d44SSepherosa Ziehau static void
connect_client(int port)29*73610d44SSepherosa Ziehau connect_client(int port)
30*73610d44SSepherosa Ziehau {
31*73610d44SSepherosa Ziehau 	struct sockaddr_in in;
32*73610d44SSepherosa Ziehau 	int s, dummy;
33*73610d44SSepherosa Ziehau 
34*73610d44SSepherosa Ziehau 	s = socket(AF_INET, SOCK_STREAM, 0);
35*73610d44SSepherosa Ziehau 	if (s < 0)
36*73610d44SSepherosa Ziehau 		err(1, "client socket failed");
37*73610d44SSepherosa Ziehau 
38*73610d44SSepherosa Ziehau 	memset(&in, 0, sizeof(in));
39*73610d44SSepherosa Ziehau 	in.sin_family = AF_INET;
40*73610d44SSepherosa Ziehau 	in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
41*73610d44SSepherosa Ziehau 	in.sin_port = htons(port);
42*73610d44SSepherosa Ziehau 	if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
43*73610d44SSepherosa Ziehau 		err(1, "connect failed");
44*73610d44SSepherosa Ziehau 
45*73610d44SSepherosa Ziehau 	sleep(WRITE_WAIT_TIME);
46*73610d44SSepherosa Ziehau 	write(s, &dummy, sizeof(dummy));
47*73610d44SSepherosa Ziehau 
48*73610d44SSepherosa Ziehau 	pause();
49*73610d44SSepherosa Ziehau 	exit(0);
50*73610d44SSepherosa Ziehau }
51*73610d44SSepherosa Ziehau 
52*73610d44SSepherosa Ziehau int
main(int argc,char * argv[])53*73610d44SSepherosa Ziehau main(int argc, char *argv[])
54*73610d44SSepherosa Ziehau {
55*73610d44SSepherosa Ziehau 	struct sockaddr_in in;
56*73610d44SSepherosa Ziehau 	int serv_s, s;
57*73610d44SSepherosa Ziehau 	int opt, port, dummy, n, status, panic, ex;
58*73610d44SSepherosa Ziehau 	struct timespec stime, etime;
59*73610d44SSepherosa Ziehau 	pid_t pid;
60*73610d44SSepherosa Ziehau 
61*73610d44SSepherosa Ziehau 	ex = 1;
62*73610d44SSepherosa Ziehau 	panic = 0;
63*73610d44SSepherosa Ziehau 
64*73610d44SSepherosa Ziehau 	port = 0;
65*73610d44SSepherosa Ziehau 	while ((opt = getopt(argc, argv, "p:")) != -1) {
66*73610d44SSepherosa Ziehau 		char *endptr;
67*73610d44SSepherosa Ziehau 
68*73610d44SSepherosa Ziehau 		switch (opt) {
69*73610d44SSepherosa Ziehau 		case 'p':
70*73610d44SSepherosa Ziehau 			port = strtol(optarg, &endptr, 0);
71*73610d44SSepherosa Ziehau 			if (*endptr != '\0')
72*73610d44SSepherosa Ziehau 				errx(1, "invalid -p");
73*73610d44SSepherosa Ziehau 			break;
74*73610d44SSepherosa Ziehau 
75*73610d44SSepherosa Ziehau 		default:
76*73610d44SSepherosa Ziehau 			usage(argv[0]);
77*73610d44SSepherosa Ziehau 		}
78*73610d44SSepherosa Ziehau 	}
79*73610d44SSepherosa Ziehau 	if (port <= 0)
80*73610d44SSepherosa Ziehau 		usage(argv[0]);
81*73610d44SSepherosa Ziehau 
82*73610d44SSepherosa Ziehau 	serv_s = socket(AF_INET, SOCK_STREAM, 0);
83*73610d44SSepherosa Ziehau 	if (serv_s < 0)
84*73610d44SSepherosa Ziehau 		err(1, "socket failed");
85*73610d44SSepherosa Ziehau 
86*73610d44SSepherosa Ziehau 	memset(&in, 0, sizeof(in));
87*73610d44SSepherosa Ziehau 	in.sin_family = AF_INET;
88*73610d44SSepherosa Ziehau 	in.sin_port = htons(port);
89*73610d44SSepherosa Ziehau 	if (bind(serv_s, (const struct sockaddr *)&in, sizeof(in)) < 0)
90*73610d44SSepherosa Ziehau 		err(1, "bind failed");
91*73610d44SSepherosa Ziehau 
92*73610d44SSepherosa Ziehau 	if (listen(serv_s, 0) < 0)
93*73610d44SSepherosa Ziehau 		err(1, "listen failed");
94*73610d44SSepherosa Ziehau 
95*73610d44SSepherosa Ziehau 	pid = fork();
96*73610d44SSepherosa Ziehau 	if (pid < 0) {
97*73610d44SSepherosa Ziehau 		err(1, "fork failed");
98*73610d44SSepherosa Ziehau 	} else if (pid == 0) {
99*73610d44SSepherosa Ziehau 		connect_client(port);
100*73610d44SSepherosa Ziehau 		abort();
101*73610d44SSepherosa Ziehau 	}
102*73610d44SSepherosa Ziehau 
103*73610d44SSepherosa Ziehau 	s = accept(serv_s, NULL, NULL);
104*73610d44SSepherosa Ziehau 	if (s < 0) {
105*73610d44SSepherosa Ziehau 		warn("accept failed");
106*73610d44SSepherosa Ziehau 		goto done;
107*73610d44SSepherosa Ziehau 	}
108*73610d44SSepherosa Ziehau 	panic = 1;
109*73610d44SSepherosa Ziehau 
110*73610d44SSepherosa Ziehau 	clock_gettime(CLOCK_MONOTONIC, &stime);
111*73610d44SSepherosa Ziehau 	n = read(s, &dummy, sizeof(dummy));
112*73610d44SSepherosa Ziehau 	if (n < 0) {
113*73610d44SSepherosa Ziehau 		warn("read failed");
114*73610d44SSepherosa Ziehau 		goto done;
115*73610d44SSepherosa Ziehau 	} else if (n != sizeof(dummy)) {
116*73610d44SSepherosa Ziehau 		warnx("read size mismatch");
117*73610d44SSepherosa Ziehau 		goto done;
118*73610d44SSepherosa Ziehau 	}
119*73610d44SSepherosa Ziehau 	clock_gettime(CLOCK_MONOTONIC, &etime);
120*73610d44SSepherosa Ziehau 
121*73610d44SSepherosa Ziehau 	if (etime.tv_sec - stime.tv_sec < READ_WAIT_MIN) {
122*73610d44SSepherosa Ziehau 		warnx("invalid wait time %ld", etime.tv_sec - stime.tv_sec);
123*73610d44SSepherosa Ziehau 		goto done;
124*73610d44SSepherosa Ziehau 	}
125*73610d44SSepherosa Ziehau 
126*73610d44SSepherosa Ziehau 	ex = 0;
127*73610d44SSepherosa Ziehau 	panic = 0;
128*73610d44SSepherosa Ziehau 	fprintf(stderr, "passed\n");
129*73610d44SSepherosa Ziehau done:
130*73610d44SSepherosa Ziehau 	kill(pid, SIGKILL);
131*73610d44SSepherosa Ziehau 	waitpid(pid, &status, 0);
132*73610d44SSepherosa Ziehau 	if (panic)
133*73610d44SSepherosa Ziehau 		abort();
134*73610d44SSepherosa Ziehau 	exit(ex);
135*73610d44SSepherosa Ziehau }
136