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