Blame


1 8a35f56c 2022-07-16 thomas /*
2 8a35f56c 2022-07-16 thomas * Copyright (c) 2016, 2019, 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 8a35f56c 2022-07-16 thomas * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
4 8a35f56c 2022-07-16 thomas * Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
5 8a35f56c 2022-07-16 thomas * Copyright (c) 2013 Florian Obser <florian@openbsd.org>
6 8a35f56c 2022-07-16 thomas *
7 8a35f56c 2022-07-16 thomas * Permission to use, copy, modify, and distribute this software for any
8 8a35f56c 2022-07-16 thomas * purpose with or without fee is hereby granted, provided that the above
9 8a35f56c 2022-07-16 thomas * copyright notice and this permission notice appear in all copies.
10 8a35f56c 2022-07-16 thomas *
11 8a35f56c 2022-07-16 thomas * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 8a35f56c 2022-07-16 thomas * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 8a35f56c 2022-07-16 thomas * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 8a35f56c 2022-07-16 thomas * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 8a35f56c 2022-07-16 thomas * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 8a35f56c 2022-07-16 thomas * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 8a35f56c 2022-07-16 thomas * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 8a35f56c 2022-07-16 thomas */
19 4fccd2fe 2023-03-08 thomas
20 4fccd2fe 2023-03-08 thomas #include "got_compat.h"
21 8a35f56c 2022-07-16 thomas
22 8a35f56c 2022-07-16 thomas #include <sys/param.h>
23 8a35f56c 2022-07-16 thomas #include <sys/ioctl.h>
24 8b925c6c 2022-07-16 thomas #include <sys/queue.h>
25 8a35f56c 2022-07-16 thomas #include <sys/wait.h>
26 8a35f56c 2022-07-16 thomas #include <sys/uio.h>
27 8a35f56c 2022-07-16 thomas #include <sys/resource.h>
28 8a35f56c 2022-07-16 thomas #include <sys/socket.h>
29 8a35f56c 2022-07-16 thomas #include <sys/stat.h>
30 8a35f56c 2022-07-16 thomas #include <sys/time.h>
31 8a35f56c 2022-07-16 thomas #include <sys/types.h>
32 8a35f56c 2022-07-16 thomas #include <sys/mman.h>
33 8a35f56c 2022-07-16 thomas #include <sys/un.h>
34 8a35f56c 2022-07-16 thomas
35 8a35f56c 2022-07-16 thomas #include <net/if.h>
36 8a35f56c 2022-07-16 thomas #include <netinet/in.h>
37 8a35f56c 2022-07-16 thomas
38 8a35f56c 2022-07-16 thomas #include <errno.h>
39 8a35f56c 2022-07-16 thomas #include <event.h>
40 8a35f56c 2022-07-16 thomas #include <fcntl.h>
41 8a35f56c 2022-07-16 thomas #include <ifaddrs.h>
42 8a35f56c 2022-07-16 thomas #include <limits.h>
43 8a35f56c 2022-07-16 thomas #include <netdb.h>
44 8a35f56c 2022-07-16 thomas #include <poll.h>
45 8a35f56c 2022-07-16 thomas #include <pwd.h>
46 8a35f56c 2022-07-16 thomas #include <stddef.h>
47 8a35f56c 2022-07-16 thomas #include <stdio.h>
48 8a35f56c 2022-07-16 thomas #include <stdlib.h>
49 8a35f56c 2022-07-16 thomas #include <string.h>
50 8a35f56c 2022-07-16 thomas #include <unistd.h>
51 8a35f56c 2022-07-16 thomas
52 8a35f56c 2022-07-16 thomas #include "got_error.h"
53 8a35f56c 2022-07-16 thomas #include "got_opentemp.h"
54 161663e7 2023-03-11 thomas #include "got_reference.h"
55 55e6cffd 2022-09-01 thomas #include "got_repository.h"
56 79e60db6 2023-11-14 thomas #include "got_privsep.h"
57 8a35f56c 2022-07-16 thomas
58 8a35f56c 2022-07-16 thomas #include "gotwebd.h"
59 e7e5fa49 2022-12-30 thomas #include "tmpl.h"
60 8a35f56c 2022-07-16 thomas
61 8a35f56c 2022-07-16 thomas #define SOCKS_BACKLOG 5
62 8a35f56c 2022-07-16 thomas #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
63 8a35f56c 2022-07-16 thomas
64 8a35f56c 2022-07-16 thomas volatile int client_cnt;
65 8a35f56c 2022-07-16 thomas
66 1f6ec068 2022-08-27 thomas static struct timeval timeout = { TIMEOUT_DEFAULT, 0 };
67 8a35f56c 2022-07-16 thomas
68 1f6ec068 2022-08-27 thomas static void sockets_sighdlr(int, short, void *);
69 f85c939f 2023-11-22 thomas static void sockets_shutdown(void);
70 1f6ec068 2022-08-27 thomas static void sockets_launch(void);
71 1f6ec068 2022-08-27 thomas static void sockets_purge(struct gotwebd *);
72 1f6ec068 2022-08-27 thomas static void sockets_accept_paused(int, short, void *);
73 1f6ec068 2022-08-27 thomas static void sockets_rlimit(int);
74 8a35f56c 2022-07-16 thomas
75 f85c939f 2023-11-22 thomas static void sockets_dispatch_main(int, short, void *);
76 f85c939f 2023-11-22 thomas static int sockets_unix_socket_listen(struct gotwebd *, struct socket *);
77 7d1d4b6f 2023-11-16 thomas static int sockets_create_socket(struct address *);
78 1f6ec068 2022-08-27 thomas static int sockets_accept_reserve(int, struct sockaddr *, socklen_t *,
79 1f6ec068 2022-08-27 thomas int, volatile int *);
80 8a35f56c 2022-07-16 thomas
81 1f6ec068 2022-08-27 thomas static struct socket *sockets_conf_new_socket_unix(struct gotwebd *,
82 1f6ec068 2022-08-27 thomas struct server *, int);
83 1f6ec068 2022-08-27 thomas static struct socket *sockets_conf_new_socket_fcgi(struct gotwebd *,
84 1f6ec068 2022-08-27 thomas struct server *, int, struct address *);
85 8a35f56c 2022-07-16 thomas
86 8a35f56c 2022-07-16 thomas int cgi_inflight = 0;
87 8a35f56c 2022-07-16 thomas
88 8a35f56c 2022-07-16 thomas void
89 f85c939f 2023-11-22 thomas sockets(struct gotwebd *env, int fd)
90 8a35f56c 2022-07-16 thomas {
91 7a4d2c24 2024-02-11 thomas struct event sighup, sigint, sigusr1, sigchld, sigterm;
92 8a35f56c 2022-07-16 thomas
93 f85c939f 2023-11-22 thomas event_init();
94 8a35f56c 2022-07-16 thomas
95 8a35f56c 2022-07-16 thomas sockets_rlimit(-1);
96 8a35f56c 2022-07-16 thomas
97 f85c939f 2023-11-22 thomas if (config_init(env) == -1)
98 f85c939f 2023-11-22 thomas fatal("failed to initialize configuration");
99 8a35f56c 2022-07-16 thomas
100 f85c939f 2023-11-22 thomas if ((env->iev_parent = malloc(sizeof(*env->iev_parent))) == NULL)
101 f85c939f 2023-11-22 thomas fatal("malloc");
102 f85c939f 2023-11-22 thomas imsg_init(&env->iev_parent->ibuf, fd);
103 f85c939f 2023-11-22 thomas env->iev_parent->handler = sockets_dispatch_main;
104 f85c939f 2023-11-22 thomas env->iev_parent->data = env->iev_parent;
105 f85c939f 2023-11-22 thomas event_set(&env->iev_parent->ev, fd, EV_READ, sockets_dispatch_main,
106 f85c939f 2023-11-22 thomas env->iev_parent);
107 f85c939f 2023-11-22 thomas event_add(&env->iev_parent->ev, NULL);
108 f422fd17 2023-11-22 thomas
109 f422fd17 2023-11-22 thomas signal(SIGPIPE, SIG_IGN);
110 f85c939f 2023-11-22 thomas
111 ea827802 2023-11-22 thomas signal_set(&sighup, SIGHUP, sockets_sighdlr, env);
112 f85c939f 2023-11-22 thomas signal_add(&sighup, NULL);
113 7a4d2c24 2024-02-11 thomas signal_set(&sigint, SIGINT, sockets_sighdlr, env);
114 7a4d2c24 2024-02-11 thomas signal_add(&sigint, NULL);
115 ea827802 2023-11-22 thomas signal_set(&sigusr1, SIGUSR1, sockets_sighdlr, env);
116 f85c939f 2023-11-22 thomas signal_add(&sigusr1, NULL);
117 f85c939f 2023-11-22 thomas signal_set(&sigchld, SIGCHLD, sockets_sighdlr, env);
118 f85c939f 2023-11-22 thomas signal_add(&sigchld, NULL);
119 7a4d2c24 2024-02-11 thomas signal_set(&sigterm, SIGTERM, sockets_sighdlr, env);
120 7a4d2c24 2024-02-11 thomas signal_add(&sigterm, NULL);
121 f85c939f 2023-11-22 thomas
122 8a35f56c 2022-07-16 thomas #ifndef PROFILE
123 9cfaa638 2023-11-14 thomas if (pledge("stdio rpath inet recvfd proc exec sendfd unveil",
124 9cfaa638 2023-11-14 thomas NULL) == -1)
125 8a35f56c 2022-07-16 thomas fatal("pledge");
126 8a35f56c 2022-07-16 thomas #endif
127 f85c939f 2023-11-22 thomas
128 f85c939f 2023-11-22 thomas event_dispatch();
129 f85c939f 2023-11-22 thomas sockets_shutdown();
130 8a35f56c 2022-07-16 thomas }
131 8a35f56c 2022-07-16 thomas
132 8a35f56c 2022-07-16 thomas void
133 8a35f56c 2022-07-16 thomas sockets_parse_sockets(struct gotwebd *env)
134 8a35f56c 2022-07-16 thomas {
135 8a35f56c 2022-07-16 thomas struct server *srv;
136 9d7714e3 2022-08-27 thomas struct address *a;
137 720c2b05 2022-08-16 thomas struct socket *new_sock = NULL;
138 9d7714e3 2022-08-27 thomas int sock_id = 1;
139 8a35f56c 2022-07-16 thomas
140 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &env->servers, entry) {
141 8a35f56c 2022-07-16 thomas if (srv->unix_socket) {
142 9d7714e3 2022-08-27 thomas new_sock = sockets_conf_new_socket_unix(env, srv,
143 9d7714e3 2022-08-27 thomas sock_id);
144 720c2b05 2022-08-16 thomas if (new_sock) {
145 9d7714e3 2022-08-27 thomas sock_id++;
146 720c2b05 2022-08-16 thomas TAILQ_INSERT_TAIL(&env->sockets, new_sock,
147 720c2b05 2022-08-16 thomas entry);
148 8a35f56c 2022-07-16 thomas }
149 9d7714e3 2022-08-27 thomas }
150 8a35f56c 2022-07-16 thomas
151 9d7714e3 2022-08-27 thomas if (srv->fcgi_socket) {
152 9d7714e3 2022-08-27 thomas if (TAILQ_EMPTY(&srv->al)) {
153 9d7714e3 2022-08-27 thomas fatalx("%s: server %s has no IP addresses to "
154 9d7714e3 2022-08-27 thomas "listen for FCGI connections", __func__,
155 9d7714e3 2022-08-27 thomas srv->name);
156 720c2b05 2022-08-16 thomas }
157 9d7714e3 2022-08-27 thomas TAILQ_FOREACH(a, &srv->al, entry) {
158 9d7714e3 2022-08-27 thomas if (a->ss.ss_family != AF_INET &&
159 9d7714e3 2022-08-27 thomas a->ss.ss_family != AF_INET6)
160 9d7714e3 2022-08-27 thomas continue;
161 9d7714e3 2022-08-27 thomas new_sock = sockets_conf_new_socket_fcgi(env,
162 9d7714e3 2022-08-27 thomas srv, sock_id, a);
163 9d7714e3 2022-08-27 thomas if (new_sock) {
164 9d7714e3 2022-08-27 thomas sock_id++;
165 9d7714e3 2022-08-27 thomas TAILQ_INSERT_TAIL(&env->sockets,
166 9d7714e3 2022-08-27 thomas new_sock, entry);
167 9d7714e3 2022-08-27 thomas }
168 8a35f56c 2022-07-16 thomas }
169 8a35f56c 2022-07-16 thomas }
170 8a35f56c 2022-07-16 thomas }
171 8a35f56c 2022-07-16 thomas }
172 8a35f56c 2022-07-16 thomas
173 1f6ec068 2022-08-27 thomas static struct socket *
174 9d7714e3 2022-08-27 thomas sockets_conf_new_socket_unix(struct gotwebd *env, struct server *srv, int id)
175 8a35f56c 2022-07-16 thomas {
176 8a35f56c 2022-07-16 thomas struct socket *sock;
177 8a35f56c 2022-07-16 thomas int n;
178 8a35f56c 2022-07-16 thomas
179 8a35f56c 2022-07-16 thomas if ((sock = calloc(1, sizeof(*sock))) == NULL)
180 8a35f56c 2022-07-16 thomas fatalx("%s: calloc", __func__);
181 8a35f56c 2022-07-16 thomas
182 8a35f56c 2022-07-16 thomas sock->conf.id = id;
183 8a35f56c 2022-07-16 thomas sock->fd = -1;
184 9d7714e3 2022-08-27 thomas sock->conf.af_type = AF_UNIX;
185 8a35f56c 2022-07-16 thomas
186 9d7714e3 2022-08-27 thomas if (strlcpy(sock->conf.unix_socket_name,
187 9d7714e3 2022-08-27 thomas srv->unix_socket_name,
188 9d7714e3 2022-08-27 thomas sizeof(sock->conf.unix_socket_name)) >=
189 9d7714e3 2022-08-27 thomas sizeof(sock->conf.unix_socket_name)) {
190 9d7714e3 2022-08-27 thomas free(sock);
191 9d7714e3 2022-08-27 thomas fatalx("%s: strlcpy", __func__);
192 720c2b05 2022-08-16 thomas }
193 8a35f56c 2022-07-16 thomas
194 8a35f56c 2022-07-16 thomas n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
195 8a35f56c 2022-07-16 thomas srv->name);
196 717a78d4 2022-08-16 thomas if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
197 8a35f56c 2022-07-16 thomas free(sock);
198 8a35f56c 2022-07-16 thomas fatalx("%s: snprintf", __func__);
199 8a35f56c 2022-07-16 thomas }
200 8a35f56c 2022-07-16 thomas
201 8a35f56c 2022-07-16 thomas if (strlcpy(sock->conf.srv_name, srv->name,
202 8a35f56c 2022-07-16 thomas sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
203 8a35f56c 2022-07-16 thomas free(sock);
204 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
205 8a35f56c 2022-07-16 thomas }
206 8a35f56c 2022-07-16 thomas
207 9d7714e3 2022-08-27 thomas return sock;
208 9d7714e3 2022-08-27 thomas }
209 720c2b05 2022-08-16 thomas
210 1f6ec068 2022-08-27 thomas static struct socket *
211 9d7714e3 2022-08-27 thomas sockets_conf_new_socket_fcgi(struct gotwebd *env, struct server *srv, int id,
212 9d7714e3 2022-08-27 thomas struct address *a)
213 9d7714e3 2022-08-27 thomas {
214 9d7714e3 2022-08-27 thomas struct socket *sock;
215 9d7714e3 2022-08-27 thomas struct address *acp;
216 9d7714e3 2022-08-27 thomas int n;
217 8a35f56c 2022-07-16 thomas
218 9d7714e3 2022-08-27 thomas if ((sock = calloc(1, sizeof(*sock))) == NULL)
219 9d7714e3 2022-08-27 thomas fatalx("%s: calloc", __func__);
220 720c2b05 2022-08-16 thomas
221 9d7714e3 2022-08-27 thomas sock->conf.id = id;
222 9d7714e3 2022-08-27 thomas sock->fd = -1;
223 9d7714e3 2022-08-27 thomas sock->conf.af_type = a->ss.ss_family;
224 9d7714e3 2022-08-27 thomas
225 e4c7e0b0 2022-08-30 thomas sock->conf.fcgi_socket_port = a->port;
226 9d7714e3 2022-08-27 thomas
227 9d7714e3 2022-08-27 thomas n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
228 9d7714e3 2022-08-27 thomas srv->name);
229 9d7714e3 2022-08-27 thomas if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
230 720c2b05 2022-08-16 thomas free(sock);
231 9d7714e3 2022-08-27 thomas fatalx("%s: snprintf", __func__);
232 9d7714e3 2022-08-27 thomas }
233 9d7714e3 2022-08-27 thomas
234 9d7714e3 2022-08-27 thomas if (strlcpy(sock->conf.srv_name, srv->name,
235 9d7714e3 2022-08-27 thomas sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
236 9d7714e3 2022-08-27 thomas free(sock);
237 9d7714e3 2022-08-27 thomas fatalx("%s: strlcpy", __func__);
238 9d7714e3 2022-08-27 thomas }
239 9d7714e3 2022-08-27 thomas
240 9d7714e3 2022-08-27 thomas acp = &sock->conf.addr;
241 9d7714e3 2022-08-27 thomas
242 9d7714e3 2022-08-27 thomas memcpy(&acp->ss, &a->ss, sizeof(acp->ss));
243 2edd250d 2023-11-16 thomas acp->slen = a->slen;
244 7d1d4b6f 2023-11-16 thomas acp->ai_family = a->ai_family;
245 7d1d4b6f 2023-11-16 thomas acp->ai_socktype = a->ai_socktype;
246 7d1d4b6f 2023-11-16 thomas acp->ai_protocol = a->ai_protocol;
247 9d7714e3 2022-08-27 thomas acp->port = a->port;
248 102d840d 2023-06-22 thomas if (*a->ifname != '\0') {
249 9d7714e3 2022-08-27 thomas if (strlcpy(acp->ifname, a->ifname,
250 9d7714e3 2022-08-27 thomas sizeof(acp->ifname)) >= sizeof(acp->ifname)) {
251 9d7714e3 2022-08-27 thomas fatalx("%s: interface name truncated",
252 9d7714e3 2022-08-27 thomas __func__);
253 9d7714e3 2022-08-27 thomas }
254 720c2b05 2022-08-16 thomas }
255 720c2b05 2022-08-16 thomas
256 8a35f56c 2022-07-16 thomas return (sock);
257 8a35f56c 2022-07-16 thomas }
258 8a35f56c 2022-07-16 thomas
259 1f6ec068 2022-08-27 thomas static void
260 8a35f56c 2022-07-16 thomas sockets_launch(void)
261 8a35f56c 2022-07-16 thomas {
262 8a35f56c 2022-07-16 thomas struct socket *sock;
263 79e60db6 2023-11-14 thomas struct server *srv;
264 79e60db6 2023-11-14 thomas const struct got_error *error;
265 8a35f56c 2022-07-16 thomas
266 90d63d47 2022-08-16 thomas TAILQ_FOREACH(sock, &gotwebd_env->sockets, entry) {
267 8a35f56c 2022-07-16 thomas log_debug("%s: configuring socket %d (%d)", __func__,
268 8a35f56c 2022-07-16 thomas sock->conf.id, sock->fd);
269 8a35f56c 2022-07-16 thomas
270 8a35f56c 2022-07-16 thomas event_set(&sock->ev, sock->fd, EV_READ | EV_PERSIST,
271 8a35f56c 2022-07-16 thomas sockets_socket_accept, sock);
272 8a35f56c 2022-07-16 thomas
273 8a35f56c 2022-07-16 thomas if (event_add(&sock->ev, NULL))
274 8a35f56c 2022-07-16 thomas fatalx("event add sock");
275 8a35f56c 2022-07-16 thomas
276 8a35f56c 2022-07-16 thomas evtimer_set(&sock->pause, sockets_accept_paused, sock);
277 8a35f56c 2022-07-16 thomas
278 8a35f56c 2022-07-16 thomas log_debug("%s: running socket listener %d", __func__,
279 8a35f56c 2022-07-16 thomas sock->conf.id);
280 8a35f56c 2022-07-16 thomas }
281 79e60db6 2023-11-14 thomas
282 79e60db6 2023-11-14 thomas TAILQ_FOREACH(srv, &gotwebd_env->servers, entry) {
283 79e60db6 2023-11-14 thomas if (unveil(srv->repos_path, "r") == -1)
284 79e60db6 2023-11-14 thomas fatal("unveil %s", srv->repos_path);
285 79e60db6 2023-11-14 thomas }
286 79e60db6 2023-11-14 thomas
287 79e60db6 2023-11-14 thomas error = got_privsep_unveil_exec_helpers();
288 79e60db6 2023-11-14 thomas if (error)
289 79e60db6 2023-11-14 thomas fatal("%s", error->msg);
290 79e60db6 2023-11-14 thomas
291 79e60db6 2023-11-14 thomas if (unveil(NULL, NULL) == -1)
292 79e60db6 2023-11-14 thomas fatal("unveil");
293 8a35f56c 2022-07-16 thomas }
294 8a35f56c 2022-07-16 thomas
295 1f6ec068 2022-08-27 thomas static void
296 8a35f56c 2022-07-16 thomas sockets_purge(struct gotwebd *env)
297 8a35f56c 2022-07-16 thomas {
298 8a35f56c 2022-07-16 thomas struct socket *sock, *tsock;
299 8a35f56c 2022-07-16 thomas
300 8a35f56c 2022-07-16 thomas /* shutdown and remove sockets */
301 90d63d47 2022-08-16 thomas TAILQ_FOREACH_SAFE(sock, &env->sockets, entry, tsock) {
302 8a35f56c 2022-07-16 thomas if (event_initialized(&sock->ev))
303 8a35f56c 2022-07-16 thomas event_del(&sock->ev);
304 8a35f56c 2022-07-16 thomas if (evtimer_initialized(&sock->evt))
305 8a35f56c 2022-07-16 thomas evtimer_del(&sock->evt);
306 8a35f56c 2022-07-16 thomas if (evtimer_initialized(&sock->pause))
307 8a35f56c 2022-07-16 thomas evtimer_del(&sock->pause);
308 8a35f56c 2022-07-16 thomas if (sock->fd != -1)
309 8a35f56c 2022-07-16 thomas close(sock->fd);
310 90d63d47 2022-08-16 thomas TAILQ_REMOVE(&env->sockets, sock, entry);
311 8a35f56c 2022-07-16 thomas }
312 8a35f56c 2022-07-16 thomas }
313 8a35f56c 2022-07-16 thomas
314 f85c939f 2023-11-22 thomas static void
315 f85c939f 2023-11-22 thomas sockets_dispatch_main(int fd, short event, void *arg)
316 8a35f56c 2022-07-16 thomas {
317 f85c939f 2023-11-22 thomas struct imsgev *iev = arg;
318 f85c939f 2023-11-22 thomas struct imsgbuf *ibuf;
319 f85c939f 2023-11-22 thomas struct imsg imsg;
320 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
321 f85c939f 2023-11-22 thomas ssize_t n;
322 f85c939f 2023-11-22 thomas int shut = 0;
323 8a35f56c 2022-07-16 thomas
324 f85c939f 2023-11-22 thomas ibuf = &iev->ibuf;
325 f85c939f 2023-11-22 thomas
326 f85c939f 2023-11-22 thomas if (event & EV_READ) {
327 f85c939f 2023-11-22 thomas if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
328 f85c939f 2023-11-22 thomas fatal("imsg_read error");
329 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
330 f85c939f 2023-11-22 thomas shut = 1;
331 8a35f56c 2022-07-16 thomas }
332 f85c939f 2023-11-22 thomas if (event & EV_WRITE) {
333 f85c939f 2023-11-22 thomas if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
334 f85c939f 2023-11-22 thomas fatal("msgbuf_write");
335 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
336 f85c939f 2023-11-22 thomas shut = 1;
337 f85c939f 2023-11-22 thomas }
338 8a35f56c 2022-07-16 thomas
339 f85c939f 2023-11-22 thomas for (;;) {
340 f85c939f 2023-11-22 thomas if ((n = imsg_get(ibuf, &imsg)) == -1)
341 f85c939f 2023-11-22 thomas fatal("imsg_get");
342 f85c939f 2023-11-22 thomas if (n == 0) /* No more messages. */
343 f85c939f 2023-11-22 thomas break;
344 f85c939f 2023-11-22 thomas
345 f85c939f 2023-11-22 thomas switch (imsg.hdr.type) {
346 f85c939f 2023-11-22 thomas case IMSG_CFG_SRV:
347 f85c939f 2023-11-22 thomas config_getserver(env, &imsg);
348 f85c939f 2023-11-22 thomas break;
349 f85c939f 2023-11-22 thomas case IMSG_CFG_SOCK:
350 f85c939f 2023-11-22 thomas config_getsock(env, &imsg);
351 f85c939f 2023-11-22 thomas break;
352 f85c939f 2023-11-22 thomas case IMSG_CFG_FD:
353 f85c939f 2023-11-22 thomas config_getfd(env, &imsg);
354 f85c939f 2023-11-22 thomas break;
355 f85c939f 2023-11-22 thomas case IMSG_CFG_DONE:
356 f85c939f 2023-11-22 thomas config_getcfg(env, &imsg);
357 f85c939f 2023-11-22 thomas break;
358 f85c939f 2023-11-22 thomas case IMSG_CTL_START:
359 f85c939f 2023-11-22 thomas sockets_launch();
360 f85c939f 2023-11-22 thomas break;
361 f85c939f 2023-11-22 thomas default:
362 f85c939f 2023-11-22 thomas fatalx("%s: unknown imsg type %d", __func__,
363 f85c939f 2023-11-22 thomas imsg.hdr.type);
364 f85c939f 2023-11-22 thomas }
365 f85c939f 2023-11-22 thomas
366 f85c939f 2023-11-22 thomas imsg_free(&imsg);
367 8a35f56c 2022-07-16 thomas }
368 8a35f56c 2022-07-16 thomas
369 f85c939f 2023-11-22 thomas if (!shut)
370 f85c939f 2023-11-22 thomas imsg_event_add(iev);
371 f85c939f 2023-11-22 thomas else {
372 f85c939f 2023-11-22 thomas /* This pipe is dead. Remove its event handler */
373 f85c939f 2023-11-22 thomas event_del(&iev->ev);
374 f85c939f 2023-11-22 thomas event_loopexit(NULL);
375 f85c939f 2023-11-22 thomas }
376 8a35f56c 2022-07-16 thomas }
377 8a35f56c 2022-07-16 thomas
378 1f6ec068 2022-08-27 thomas static void
379 8a35f56c 2022-07-16 thomas sockets_sighdlr(int sig, short event, void *arg)
380 8a35f56c 2022-07-16 thomas {
381 8a35f56c 2022-07-16 thomas switch (sig) {
382 8a35f56c 2022-07-16 thomas case SIGHUP:
383 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGHUP", __func__);
384 8a35f56c 2022-07-16 thomas break;
385 8a35f56c 2022-07-16 thomas case SIGPIPE:
386 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGPIPE", __func__);
387 8a35f56c 2022-07-16 thomas break;
388 8a35f56c 2022-07-16 thomas case SIGUSR1:
389 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGUSR1", __func__);
390 8a35f56c 2022-07-16 thomas break;
391 8a35f56c 2022-07-16 thomas case SIGCHLD:
392 7a4d2c24 2024-02-11 thomas break;
393 7a4d2c24 2024-02-11 thomas case SIGINT:
394 7a4d2c24 2024-02-11 thomas case SIGTERM:
395 7a4d2c24 2024-02-11 thomas sockets_shutdown();
396 8a35f56c 2022-07-16 thomas break;
397 8a35f56c 2022-07-16 thomas default:
398 8a35f56c 2022-07-16 thomas log_info("SIGNAL: %d", sig);
399 8a35f56c 2022-07-16 thomas fatalx("unexpected signal");
400 8a35f56c 2022-07-16 thomas }
401 8a35f56c 2022-07-16 thomas }
402 8a35f56c 2022-07-16 thomas
403 f85c939f 2023-11-22 thomas static void
404 8a35f56c 2022-07-16 thomas sockets_shutdown(void)
405 8a35f56c 2022-07-16 thomas {
406 8a35f56c 2022-07-16 thomas struct server *srv, *tsrv;
407 8a35f56c 2022-07-16 thomas struct socket *sock, *tsock;
408 8a35f56c 2022-07-16 thomas
409 8a35f56c 2022-07-16 thomas sockets_purge(gotwebd_env);
410 8a35f56c 2022-07-16 thomas
411 8a35f56c 2022-07-16 thomas /* clean sockets */
412 90d63d47 2022-08-16 thomas TAILQ_FOREACH_SAFE(sock, &gotwebd_env->sockets, entry, tsock) {
413 90d63d47 2022-08-16 thomas TAILQ_REMOVE(&gotwebd_env->sockets, sock, entry);
414 8a35f56c 2022-07-16 thomas close(sock->fd);
415 8a35f56c 2022-07-16 thomas free(sock);
416 8a35f56c 2022-07-16 thomas }
417 8a35f56c 2022-07-16 thomas
418 8a35f56c 2022-07-16 thomas /* clean servers */
419 ab5bda7e 2023-11-22 thomas TAILQ_FOREACH_SAFE(srv, &gotwebd_env->servers, entry, tsrv)
420 8a35f56c 2022-07-16 thomas free(srv);
421 8a35f56c 2022-07-16 thomas
422 8a35f56c 2022-07-16 thomas free(gotwebd_env);
423 7a4d2c24 2024-02-11 thomas
424 7a4d2c24 2024-02-11 thomas exit(0);
425 8a35f56c 2022-07-16 thomas }
426 8a35f56c 2022-07-16 thomas
427 8a35f56c 2022-07-16 thomas int
428 8a35f56c 2022-07-16 thomas sockets_privinit(struct gotwebd *env, struct socket *sock)
429 8a35f56c 2022-07-16 thomas {
430 720c2b05 2022-08-16 thomas if (sock->conf.af_type == AF_UNIX) {
431 8a35f56c 2022-07-16 thomas log_debug("%s: initializing unix socket %s", __func__,
432 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
433 f85c939f 2023-11-22 thomas sock->fd = sockets_unix_socket_listen(env, sock);
434 8a35f56c 2022-07-16 thomas if (sock->fd == -1) {
435 8a35f56c 2022-07-16 thomas log_warnx("%s: create unix socket failed", __func__);
436 8a35f56c 2022-07-16 thomas return -1;
437 8a35f56c 2022-07-16 thomas }
438 8a35f56c 2022-07-16 thomas }
439 8a35f56c 2022-07-16 thomas
440 720c2b05 2022-08-16 thomas if (sock->conf.af_type == AF_INET || sock->conf.af_type == AF_INET6) {
441 720c2b05 2022-08-16 thomas log_debug("%s: initializing %s FCGI socket on port %d for %s",
442 720c2b05 2022-08-16 thomas __func__, sock->conf.af_type == AF_INET ? "inet" : "inet6",
443 720c2b05 2022-08-16 thomas sock->conf.fcgi_socket_port, sock->conf.name);
444 7d1d4b6f 2023-11-16 thomas sock->fd = sockets_create_socket(&sock->conf.addr);
445 8a35f56c 2022-07-16 thomas if (sock->fd == -1) {
446 9d7714e3 2022-08-27 thomas log_warnx("%s: create FCGI socket failed", __func__);
447 8a35f56c 2022-07-16 thomas return -1;
448 8a35f56c 2022-07-16 thomas }
449 8a35f56c 2022-07-16 thomas }
450 8a35f56c 2022-07-16 thomas
451 8a35f56c 2022-07-16 thomas return 0;
452 8a35f56c 2022-07-16 thomas }
453 8a35f56c 2022-07-16 thomas
454 1f6ec068 2022-08-27 thomas static int
455 f85c939f 2023-11-22 thomas sockets_unix_socket_listen(struct gotwebd *env, struct socket *sock)
456 8a35f56c 2022-07-16 thomas {
457 8a35f56c 2022-07-16 thomas struct sockaddr_un sun;
458 8a35f56c 2022-07-16 thomas struct socket *tsock;
459 8a35f56c 2022-07-16 thomas int u_fd = -1;
460 8a35f56c 2022-07-16 thomas mode_t old_umask, mode;
461 8a35f56c 2022-07-16 thomas
462 90d63d47 2022-08-16 thomas TAILQ_FOREACH(tsock, &env->sockets, entry) {
463 8a35f56c 2022-07-16 thomas if (strcmp(tsock->conf.unix_socket_name,
464 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name) == 0 &&
465 8a35f56c 2022-07-16 thomas tsock->fd != -1)
466 8a35f56c 2022-07-16 thomas return (tsock->fd);
467 8a35f56c 2022-07-16 thomas }
468 8a35f56c 2022-07-16 thomas
469 dd7a7d5b 2022-07-16 thomas /* TA: FIXME: this needs upstreaming. */
470 dd7a7d5b 2022-07-16 thomas int socket_flags = SOCK_STREAM | SOCK_NONBLOCK;
471 dd7a7d5b 2022-07-16 thomas #ifdef SOCK_CLOEXEC
472 dd7a7d5b 2022-07-16 thomas socket_flags |= SOCK_CLOEXEC;
473 dd7a7d5b 2022-07-16 thomas #endif
474 dd7a7d5b 2022-07-16 thomas u_fd = socket(AF_UNIX, socket_flags, 0);
475 8a35f56c 2022-07-16 thomas if (u_fd == -1) {
476 8a35f56c 2022-07-16 thomas log_warn("%s: socket", __func__);
477 8a35f56c 2022-07-16 thomas return -1;
478 8a35f56c 2022-07-16 thomas }
479 8a35f56c 2022-07-16 thomas
480 8a35f56c 2022-07-16 thomas sun.sun_family = AF_UNIX;
481 8a35f56c 2022-07-16 thomas if (strlcpy(sun.sun_path, sock->conf.unix_socket_name,
482 8a35f56c 2022-07-16 thomas sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
483 8a35f56c 2022-07-16 thomas log_warn("%s: %s name too long", __func__,
484 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
485 8a35f56c 2022-07-16 thomas close(u_fd);
486 8a35f56c 2022-07-16 thomas return -1;
487 8a35f56c 2022-07-16 thomas }
488 8a35f56c 2022-07-16 thomas
489 8a35f56c 2022-07-16 thomas if (unlink(sock->conf.unix_socket_name) == -1) {
490 8a35f56c 2022-07-16 thomas if (errno != ENOENT) {
491 8a35f56c 2022-07-16 thomas log_warn("%s: unlink %s", __func__,
492 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
493 8a35f56c 2022-07-16 thomas close(u_fd);
494 8a35f56c 2022-07-16 thomas return -1;
495 8a35f56c 2022-07-16 thomas }
496 8a35f56c 2022-07-16 thomas }
497 8a35f56c 2022-07-16 thomas
498 8a35f56c 2022-07-16 thomas old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
499 8a35f56c 2022-07-16 thomas mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
500 8a35f56c 2022-07-16 thomas
501 8a35f56c 2022-07-16 thomas if (bind(u_fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
502 8a35f56c 2022-07-16 thomas log_warn("%s: bind: %s", __func__, sock->conf.unix_socket_name);
503 8a35f56c 2022-07-16 thomas close(u_fd);
504 8a35f56c 2022-07-16 thomas (void)umask(old_umask);
505 8a35f56c 2022-07-16 thomas return -1;
506 8a35f56c 2022-07-16 thomas }
507 8a35f56c 2022-07-16 thomas
508 8a35f56c 2022-07-16 thomas (void)umask(old_umask);
509 8a35f56c 2022-07-16 thomas
510 8a35f56c 2022-07-16 thomas if (chmod(sock->conf.unix_socket_name, mode) == -1) {
511 8a35f56c 2022-07-16 thomas log_warn("%s: chmod", __func__);
512 8a35f56c 2022-07-16 thomas close(u_fd);
513 8a35f56c 2022-07-16 thomas (void)unlink(sock->conf.unix_socket_name);
514 8a35f56c 2022-07-16 thomas return -1;
515 8a35f56c 2022-07-16 thomas }
516 8a35f56c 2022-07-16 thomas
517 f85c939f 2023-11-22 thomas if (chown(sock->conf.unix_socket_name, env->pw->pw_uid,
518 f85c939f 2023-11-22 thomas env->pw->pw_gid) == -1) {
519 8a35f56c 2022-07-16 thomas log_warn("%s: chown", __func__);
520 8a35f56c 2022-07-16 thomas close(u_fd);
521 8a35f56c 2022-07-16 thomas (void)unlink(sock->conf.unix_socket_name);
522 8a35f56c 2022-07-16 thomas return -1;
523 8a35f56c 2022-07-16 thomas }
524 8a35f56c 2022-07-16 thomas
525 8a35f56c 2022-07-16 thomas if (listen(u_fd, SOCKS_BACKLOG) == -1) {
526 8a35f56c 2022-07-16 thomas log_warn("%s: listen", __func__);
527 8a35f56c 2022-07-16 thomas return -1;
528 8a35f56c 2022-07-16 thomas }
529 8a35f56c 2022-07-16 thomas
530 8a35f56c 2022-07-16 thomas return u_fd;
531 8a35f56c 2022-07-16 thomas }
532 8a35f56c 2022-07-16 thomas
533 1f6ec068 2022-08-27 thomas static int
534 7d1d4b6f 2023-11-16 thomas sockets_create_socket(struct address *a)
535 8a35f56c 2022-07-16 thomas {
536 8a35f56c 2022-07-16 thomas int fd = -1, o_val = 1, flags;
537 8a35f56c 2022-07-16 thomas
538 7d1d4b6f 2023-11-16 thomas fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
539 9d7714e3 2022-08-27 thomas if (fd == -1)
540 9d7714e3 2022-08-27 thomas return -1;
541 8a35f56c 2022-07-16 thomas
542 9d7714e3 2022-08-27 thomas log_debug("%s: opened socket (%d) for %s", __func__,
543 9d7714e3 2022-08-27 thomas fd, a->ifname);
544 8a35f56c 2022-07-16 thomas
545 9d7714e3 2022-08-27 thomas if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &o_val,
546 9d7714e3 2022-08-27 thomas sizeof(int)) == -1) {
547 9d7714e3 2022-08-27 thomas log_warn("%s: setsockopt error", __func__);
548 9d7714e3 2022-08-27 thomas close(fd);
549 9d7714e3 2022-08-27 thomas return -1;
550 9d7714e3 2022-08-27 thomas }
551 8a35f56c 2022-07-16 thomas
552 9d7714e3 2022-08-27 thomas /* non-blocking */
553 9d7714e3 2022-08-27 thomas flags = fcntl(fd, F_GETFL);
554 9d7714e3 2022-08-27 thomas flags |= O_NONBLOCK;
555 9d7714e3 2022-08-27 thomas if (fcntl(fd, F_SETFL, flags) == -1) {
556 9d7714e3 2022-08-27 thomas log_info("%s: could not enable non-blocking I/O", __func__);
557 9d7714e3 2022-08-27 thomas close(fd);
558 9d7714e3 2022-08-27 thomas return -1;
559 9d7714e3 2022-08-27 thomas }
560 8a35f56c 2022-07-16 thomas
561 2edd250d 2023-11-16 thomas if (bind(fd, (struct sockaddr *)&a->ss, a->slen) == -1) {
562 9d7714e3 2022-08-27 thomas close(fd);
563 7d1d4b6f 2023-11-16 thomas log_info("%s: can't bind to port %d", __func__, a->port);
564 9d7714e3 2022-08-27 thomas return -1;
565 8a35f56c 2022-07-16 thomas }
566 8a35f56c 2022-07-16 thomas
567 9d7714e3 2022-08-27 thomas if (listen(fd, SOMAXCONN) == -1) {
568 9d7714e3 2022-08-27 thomas log_warn("%s, unable to listen on socket", __func__);
569 9d7714e3 2022-08-27 thomas close(fd);
570 9d7714e3 2022-08-27 thomas return -1;
571 9d7714e3 2022-08-27 thomas }
572 9d7714e3 2022-08-27 thomas
573 8a35f56c 2022-07-16 thomas return (fd);
574 8a35f56c 2022-07-16 thomas }
575 8a35f56c 2022-07-16 thomas
576 1f6ec068 2022-08-27 thomas static int
577 8a35f56c 2022-07-16 thomas sockets_accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
578 8a35f56c 2022-07-16 thomas int reserve, volatile int *counter)
579 8a35f56c 2022-07-16 thomas {
580 8a35f56c 2022-07-16 thomas int ret;
581 8a35f56c 2022-07-16 thomas
582 8a35f56c 2022-07-16 thomas if (getdtablecount() + reserve +
583 8a35f56c 2022-07-16 thomas ((*counter + 1) * FD_NEEDED) >= getdtablesize()) {
584 8a35f56c 2022-07-16 thomas log_debug("inflight fds exceeded");
585 8a35f56c 2022-07-16 thomas errno = EMFILE;
586 8a35f56c 2022-07-16 thomas return -1;
587 8a35f56c 2022-07-16 thomas }
588 5ae43732 2022-07-16 thomas /* TA: This needs fixing upstream. */
589 5ae43732 2022-07-16 thomas #ifdef __APPLE__
590 5ae43732 2022-07-16 thomas ret = accept(sockfd, addr, addrlen);
591 5ae43732 2022-07-16 thomas #else
592 5ae43732 2022-07-16 thomas ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
593 5ae43732 2022-07-16 thomas #endif
594 8a35f56c 2022-07-16 thomas
595 5ae43732 2022-07-16 thomas if (ret > -1) {
596 8a35f56c 2022-07-16 thomas (*counter)++;
597 8a35f56c 2022-07-16 thomas log_debug("inflight incremented, now %d", *counter);
598 8a35f56c 2022-07-16 thomas }
599 8a35f56c 2022-07-16 thomas
600 8a35f56c 2022-07-16 thomas return ret;
601 8a35f56c 2022-07-16 thomas }
602 8a35f56c 2022-07-16 thomas
603 1f6ec068 2022-08-27 thomas static void
604 8a35f56c 2022-07-16 thomas sockets_accept_paused(int fd, short events, void *arg)
605 8a35f56c 2022-07-16 thomas {
606 8a35f56c 2022-07-16 thomas struct socket *sock = (struct socket *)arg;
607 8a35f56c 2022-07-16 thomas
608 8a35f56c 2022-07-16 thomas event_add(&sock->ev, NULL);
609 8a35f56c 2022-07-16 thomas }
610 8a35f56c 2022-07-16 thomas
611 8a35f56c 2022-07-16 thomas void
612 8a35f56c 2022-07-16 thomas sockets_socket_accept(int fd, short event, void *arg)
613 8a35f56c 2022-07-16 thomas {
614 8a35f56c 2022-07-16 thomas struct socket *sock = (struct socket *)arg;
615 8a35f56c 2022-07-16 thomas struct sockaddr_storage ss;
616 8a35f56c 2022-07-16 thomas struct timeval backoff;
617 8a35f56c 2022-07-16 thomas struct request *c = NULL;
618 8a35f56c 2022-07-16 thomas socklen_t len;
619 8a35f56c 2022-07-16 thomas int s;
620 8a35f56c 2022-07-16 thomas
621 8a35f56c 2022-07-16 thomas backoff.tv_sec = 1;
622 8a35f56c 2022-07-16 thomas backoff.tv_usec = 0;
623 8a35f56c 2022-07-16 thomas
624 8a35f56c 2022-07-16 thomas event_add(&sock->ev, NULL);
625 8a35f56c 2022-07-16 thomas if (event & EV_TIMEOUT)
626 8a35f56c 2022-07-16 thomas return;
627 8a35f56c 2022-07-16 thomas
628 8a35f56c 2022-07-16 thomas len = sizeof(ss);
629 8a35f56c 2022-07-16 thomas
630 8a35f56c 2022-07-16 thomas s = sockets_accept_reserve(fd, (struct sockaddr *)&ss, &len,
631 8a35f56c 2022-07-16 thomas FD_RESERVE, &cgi_inflight);
632 8a35f56c 2022-07-16 thomas
633 8a35f56c 2022-07-16 thomas if (s == -1) {
634 8a35f56c 2022-07-16 thomas switch (errno) {
635 8a35f56c 2022-07-16 thomas case EINTR:
636 8a35f56c 2022-07-16 thomas case EWOULDBLOCK:
637 8a35f56c 2022-07-16 thomas case ECONNABORTED:
638 8a35f56c 2022-07-16 thomas return;
639 8a35f56c 2022-07-16 thomas case EMFILE:
640 8a35f56c 2022-07-16 thomas case ENFILE:
641 8a35f56c 2022-07-16 thomas event_del(&sock->ev);
642 8a35f56c 2022-07-16 thomas evtimer_add(&sock->pause, &backoff);
643 8a35f56c 2022-07-16 thomas return;
644 8a35f56c 2022-07-16 thomas default:
645 8a35f56c 2022-07-16 thomas log_warn("%s: accept", __func__);
646 8a35f56c 2022-07-16 thomas }
647 8a35f56c 2022-07-16 thomas }
648 8a35f56c 2022-07-16 thomas
649 8a35f56c 2022-07-16 thomas if (client_cnt > GOTWEBD_MAXCLIENTS)
650 8a35f56c 2022-07-16 thomas goto err;
651 8a35f56c 2022-07-16 thomas
652 8a35f56c 2022-07-16 thomas c = calloc(1, sizeof(struct request));
653 8a35f56c 2022-07-16 thomas if (c == NULL) {
654 e7e5fa49 2022-12-30 thomas log_warn("%s", __func__);
655 e7e5fa49 2022-12-30 thomas close(s);
656 e7e5fa49 2022-12-30 thomas cgi_inflight--;
657 e7e5fa49 2022-12-30 thomas return;
658 e7e5fa49 2022-12-30 thomas }
659 e7e5fa49 2022-12-30 thomas
660 d8bf4f25 2023-09-14 thomas c->tp = template(c, &fcgi_write, c->outbuf, sizeof(c->outbuf));
661 e7e5fa49 2022-12-30 thomas if (c->tp == NULL) {
662 8a35f56c 2022-07-16 thomas log_warn("%s", __func__);
663 8a35f56c 2022-07-16 thomas close(s);
664 8a35f56c 2022-07-16 thomas cgi_inflight--;
665 e7e5fa49 2022-12-30 thomas free(c);
666 8a35f56c 2022-07-16 thomas return;
667 8a35f56c 2022-07-16 thomas }
668 8a35f56c 2022-07-16 thomas
669 8a35f56c 2022-07-16 thomas c->fd = s;
670 8a35f56c 2022-07-16 thomas c->sock = sock;
671 8a35f56c 2022-07-16 thomas memcpy(c->priv_fd, sock->priv_fd, sizeof(c->priv_fd));
672 8a35f56c 2022-07-16 thomas c->buf_pos = 0;
673 8a35f56c 2022-07-16 thomas c->buf_len = 0;
674 8a35f56c 2022-07-16 thomas c->request_started = 0;
675 8a35f56c 2022-07-16 thomas c->sock->client_status = CLIENT_CONNECT;
676 8a35f56c 2022-07-16 thomas
677 2e9bd5cb 2023-03-10 thomas event_set(&c->ev, s, EV_READ|EV_PERSIST, fcgi_request, c);
678 8a35f56c 2022-07-16 thomas event_add(&c->ev, NULL);
679 8a35f56c 2022-07-16 thomas
680 8a35f56c 2022-07-16 thomas evtimer_set(&c->tmo, fcgi_timeout, c);
681 8a35f56c 2022-07-16 thomas evtimer_add(&c->tmo, &timeout);
682 8a35f56c 2022-07-16 thomas
683 8a35f56c 2022-07-16 thomas client_cnt++;
684 8a35f56c 2022-07-16 thomas
685 8a35f56c 2022-07-16 thomas return;
686 8a35f56c 2022-07-16 thomas err:
687 8a35f56c 2022-07-16 thomas cgi_inflight--;
688 8a35f56c 2022-07-16 thomas close(s);
689 8a35f56c 2022-07-16 thomas if (c != NULL)
690 8a35f56c 2022-07-16 thomas free(c);
691 8a35f56c 2022-07-16 thomas }
692 8a35f56c 2022-07-16 thomas
693 1f6ec068 2022-08-27 thomas static void
694 8a35f56c 2022-07-16 thomas sockets_rlimit(int maxfd)
695 8a35f56c 2022-07-16 thomas {
696 8a35f56c 2022-07-16 thomas struct rlimit rl;
697 8a35f56c 2022-07-16 thomas
698 8a35f56c 2022-07-16 thomas if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
699 8a35f56c 2022-07-16 thomas fatal("%s: failed to get resource limit", __func__);
700 ceac46c9 2022-07-17 thomas log_debug("%s: max open files %llu", __func__,
701 ceac46c9 2022-07-17 thomas (unsigned long long)rl.rlim_max);
702 8a35f56c 2022-07-16 thomas
703 8a35f56c 2022-07-16 thomas /*
704 8a35f56c 2022-07-16 thomas * Allow the maximum number of open file descriptors for this
705 8a35f56c 2022-07-16 thomas * login class (which should be the class "daemon" by default).
706 8a35f56c 2022-07-16 thomas */
707 8a35f56c 2022-07-16 thomas if (maxfd == -1)
708 8a35f56c 2022-07-16 thomas rl.rlim_cur = rl.rlim_max;
709 8a35f56c 2022-07-16 thomas else
710 8a35f56c 2022-07-16 thomas rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd);
711 8a35f56c 2022-07-16 thomas if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
712 8a35f56c 2022-07-16 thomas fatal("%s: failed to set resource limit", __func__);
713 ff36aeea 2022-07-16 thomas }