1 #include <sys/types.h>
2 #include <sys/socket.h>
3 
4 #include <arpa/inet.h>
5 #include <netinet/in.h>
6 
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 
13 static void	mainloop(int, const struct sockaddr_in *);
14 
15 static void
16 usage(const char *cmd)
17 {
18 	fprintf(stderr, "%s -p port [-i n_instance] [-r]\n", cmd);
19 	exit(1);
20 }
21 
22 static int
23 create_socket(const struct sockaddr_in *in, int reuseport)
24 {
25 	int serv_s, on;
26 
27 	serv_s = socket(AF_INET, SOCK_STREAM, 0);
28 	if (serv_s < 0) {
29 		fprintf(stderr, "socket failed: %d\n", errno);
30 		exit(1);
31 	}
32 
33 	on = 1;
34 	if (!reuseport) {
35 		if (setsockopt(serv_s, SOL_SOCKET, SO_REUSEADDR,
36 		    &on, sizeof(on)) < 0) {
37 			fprintf(stderr, "setsockopt(REUSEADDR) failed: %d\n",
38 			    errno);
39 			exit(1);
40 		}
41 	} else {
42 		if (setsockopt(serv_s, SOL_SOCKET, SO_REUSEPORT,
43 		    &on, sizeof(on)) < 0) {
44 			fprintf(stderr, "setsockopt(REUSEPORT) failed: %d\n",
45 			    errno);
46 			exit(1);
47 		}
48 	}
49 
50 	if (bind(serv_s, (const struct sockaddr *)in, sizeof(*in)) < 0) {
51 		fprintf(stderr, "bind failed: %d\n", errno);
52 		exit(1);
53 	}
54 
55 	if (listen(serv_s, -1) < 0) {
56 		fprintf(stderr, "listen failed: %d\n", errno);
57 		exit(1);
58 	}
59 	return serv_s;
60 }
61 
62 int
63 main(int argc, char *argv[])
64 {
65 	struct sockaddr_in in;
66 	int opt, ninst, serv_s, i, reuseport;
67 
68 	memset(&in, 0, sizeof(in));
69 	in.sin_family = AF_INET;
70 	in.sin_addr.s_addr = INADDR_ANY;
71 
72 	ninst = 1;
73 	reuseport = 0;
74 
75 	while ((opt = getopt(argc, argv, "p:i:r")) != -1) {
76 		switch (opt) {
77 		case 'p':
78 			in.sin_port = htons(atoi(optarg));
79 			break;
80 
81 		case 'i':
82 			ninst = atoi(optarg);
83 			break;
84 
85 		case 'r':
86 			reuseport = 1;
87 			break;
88 
89 		default:
90 			usage(argv[0]);
91 		}
92 	}
93 
94 	if (ninst < 1 || in.sin_port == 0)
95 		usage(argv[0]);
96 
97 	serv_s = -1;
98 	if (!reuseport)
99 		serv_s = create_socket(&in, 0);
100 
101 	for (i = 1; i < ninst; ++i) {
102 		pid_t pid;
103 
104 		pid = fork();
105 		if (pid == 0) {
106 			mainloop(serv_s, &in);
107 			exit(0);
108 		} else if (pid < 0) {
109 			fprintf(stderr, "fork failed: %d\n", errno);
110 		}
111 	}
112 
113 	mainloop(serv_s, &in);
114 	exit(0);
115 }
116 
117 static void
118 mainloop(int serv_s, const struct sockaddr_in *in)
119 {
120 	if (serv_s < 0)
121 		serv_s = create_socket(in, 1);
122 
123 	for (;;) {
124 		int s;
125 
126 		s = accept(serv_s, NULL, NULL);
127 		if (s >= 0)
128 			close(s);
129 	}
130 	/* NEVER REACHED */
131 }
132