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