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