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