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 ea827802 2023-11-22 thomas struct event sighup, sigusr1, sigchld;
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 ea827802 2023-11-22 thomas signal_set(&sigusr1, SIGUSR1, sockets_sighdlr, env);
114 f85c939f 2023-11-22 thomas signal_add(&sigusr1, NULL);
115 f85c939f 2023-11-22 thomas signal_set(&sigchld, SIGCHLD, sockets_sighdlr, env);
116 f85c939f 2023-11-22 thomas signal_add(&sigchld, NULL);
117 f85c939f 2023-11-22 thomas
118 8a35f56c 2022-07-16 thomas #ifndef PROFILE
119 9cfaa638 2023-11-14 thomas if (pledge("stdio rpath inet recvfd proc exec sendfd unveil",
120 9cfaa638 2023-11-14 thomas NULL) == -1)
121 8a35f56c 2022-07-16 thomas fatal("pledge");
122 8a35f56c 2022-07-16 thomas #endif
123 f85c939f 2023-11-22 thomas
124 f85c939f 2023-11-22 thomas event_dispatch();
125 f85c939f 2023-11-22 thomas sockets_shutdown();
126 8a35f56c 2022-07-16 thomas }
127 8a35f56c 2022-07-16 thomas
128 8a35f56c 2022-07-16 thomas void
129 8a35f56c 2022-07-16 thomas sockets_parse_sockets(struct gotwebd *env)
130 8a35f56c 2022-07-16 thomas {
131 8a35f56c 2022-07-16 thomas struct server *srv;
132 9d7714e3 2022-08-27 thomas struct address *a;
133 720c2b05 2022-08-16 thomas struct socket *new_sock = NULL;
134 9d7714e3 2022-08-27 thomas int sock_id = 1;
135 8a35f56c 2022-07-16 thomas
136 90d63d47 2022-08-16 thomas TAILQ_FOREACH(srv, &env->servers, entry) {
137 8a35f56c 2022-07-16 thomas if (srv->unix_socket) {
138 9d7714e3 2022-08-27 thomas new_sock = sockets_conf_new_socket_unix(env, srv,
139 9d7714e3 2022-08-27 thomas sock_id);
140 720c2b05 2022-08-16 thomas if (new_sock) {
141 9d7714e3 2022-08-27 thomas sock_id++;
142 720c2b05 2022-08-16 thomas TAILQ_INSERT_TAIL(&env->sockets, new_sock,
143 720c2b05 2022-08-16 thomas entry);
144 8a35f56c 2022-07-16 thomas }
145 9d7714e3 2022-08-27 thomas }
146 8a35f56c 2022-07-16 thomas
147 9d7714e3 2022-08-27 thomas if (srv->fcgi_socket) {
148 9d7714e3 2022-08-27 thomas if (TAILQ_EMPTY(&srv->al)) {
149 9d7714e3 2022-08-27 thomas fatalx("%s: server %s has no IP addresses to "
150 9d7714e3 2022-08-27 thomas "listen for FCGI connections", __func__,
151 9d7714e3 2022-08-27 thomas srv->name);
152 720c2b05 2022-08-16 thomas }
153 9d7714e3 2022-08-27 thomas TAILQ_FOREACH(a, &srv->al, entry) {
154 9d7714e3 2022-08-27 thomas if (a->ss.ss_family != AF_INET &&
155 9d7714e3 2022-08-27 thomas a->ss.ss_family != AF_INET6)
156 9d7714e3 2022-08-27 thomas continue;
157 9d7714e3 2022-08-27 thomas new_sock = sockets_conf_new_socket_fcgi(env,
158 9d7714e3 2022-08-27 thomas srv, sock_id, a);
159 9d7714e3 2022-08-27 thomas if (new_sock) {
160 9d7714e3 2022-08-27 thomas sock_id++;
161 9d7714e3 2022-08-27 thomas TAILQ_INSERT_TAIL(&env->sockets,
162 9d7714e3 2022-08-27 thomas new_sock, entry);
163 9d7714e3 2022-08-27 thomas }
164 8a35f56c 2022-07-16 thomas }
165 8a35f56c 2022-07-16 thomas }
166 8a35f56c 2022-07-16 thomas }
167 8a35f56c 2022-07-16 thomas }
168 8a35f56c 2022-07-16 thomas
169 1f6ec068 2022-08-27 thomas static struct socket *
170 9d7714e3 2022-08-27 thomas sockets_conf_new_socket_unix(struct gotwebd *env, struct server *srv, int id)
171 8a35f56c 2022-07-16 thomas {
172 8a35f56c 2022-07-16 thomas struct socket *sock;
173 8a35f56c 2022-07-16 thomas int n;
174 8a35f56c 2022-07-16 thomas
175 8a35f56c 2022-07-16 thomas if ((sock = calloc(1, sizeof(*sock))) == NULL)
176 8a35f56c 2022-07-16 thomas fatalx("%s: calloc", __func__);
177 8a35f56c 2022-07-16 thomas
178 8a35f56c 2022-07-16 thomas sock->conf.id = id;
179 8a35f56c 2022-07-16 thomas sock->fd = -1;
180 9d7714e3 2022-08-27 thomas sock->conf.af_type = AF_UNIX;
181 8a35f56c 2022-07-16 thomas
182 9d7714e3 2022-08-27 thomas if (strlcpy(sock->conf.unix_socket_name,
183 9d7714e3 2022-08-27 thomas srv->unix_socket_name,
184 9d7714e3 2022-08-27 thomas sizeof(sock->conf.unix_socket_name)) >=
185 9d7714e3 2022-08-27 thomas sizeof(sock->conf.unix_socket_name)) {
186 9d7714e3 2022-08-27 thomas free(sock);
187 9d7714e3 2022-08-27 thomas fatalx("%s: strlcpy", __func__);
188 720c2b05 2022-08-16 thomas }
189 8a35f56c 2022-07-16 thomas
190 8a35f56c 2022-07-16 thomas n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
191 8a35f56c 2022-07-16 thomas srv->name);
192 717a78d4 2022-08-16 thomas if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
193 8a35f56c 2022-07-16 thomas free(sock);
194 8a35f56c 2022-07-16 thomas fatalx("%s: snprintf", __func__);
195 8a35f56c 2022-07-16 thomas }
196 8a35f56c 2022-07-16 thomas
197 8a35f56c 2022-07-16 thomas if (strlcpy(sock->conf.srv_name, srv->name,
198 8a35f56c 2022-07-16 thomas sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
199 8a35f56c 2022-07-16 thomas free(sock);
200 8a35f56c 2022-07-16 thomas fatalx("%s: strlcpy", __func__);
201 8a35f56c 2022-07-16 thomas }
202 8a35f56c 2022-07-16 thomas
203 9d7714e3 2022-08-27 thomas return sock;
204 9d7714e3 2022-08-27 thomas }
205 720c2b05 2022-08-16 thomas
206 1f6ec068 2022-08-27 thomas static struct socket *
207 9d7714e3 2022-08-27 thomas sockets_conf_new_socket_fcgi(struct gotwebd *env, struct server *srv, int id,
208 9d7714e3 2022-08-27 thomas struct address *a)
209 9d7714e3 2022-08-27 thomas {
210 9d7714e3 2022-08-27 thomas struct socket *sock;
211 9d7714e3 2022-08-27 thomas struct address *acp;
212 9d7714e3 2022-08-27 thomas int n;
213 8a35f56c 2022-07-16 thomas
214 9d7714e3 2022-08-27 thomas if ((sock = calloc(1, sizeof(*sock))) == NULL)
215 9d7714e3 2022-08-27 thomas fatalx("%s: calloc", __func__);
216 720c2b05 2022-08-16 thomas
217 9d7714e3 2022-08-27 thomas sock->conf.id = id;
218 9d7714e3 2022-08-27 thomas sock->fd = -1;
219 9d7714e3 2022-08-27 thomas sock->conf.af_type = a->ss.ss_family;
220 9d7714e3 2022-08-27 thomas
221 e4c7e0b0 2022-08-30 thomas sock->conf.fcgi_socket_port = a->port;
222 9d7714e3 2022-08-27 thomas
223 9d7714e3 2022-08-27 thomas n = snprintf(sock->conf.name, GOTWEBD_MAXTEXT, "%s_parent",
224 9d7714e3 2022-08-27 thomas srv->name);
225 9d7714e3 2022-08-27 thomas if (n < 0 || (size_t)n >= GOTWEBD_MAXTEXT) {
226 720c2b05 2022-08-16 thomas free(sock);
227 9d7714e3 2022-08-27 thomas fatalx("%s: snprintf", __func__);
228 9d7714e3 2022-08-27 thomas }
229 9d7714e3 2022-08-27 thomas
230 9d7714e3 2022-08-27 thomas if (strlcpy(sock->conf.srv_name, srv->name,
231 9d7714e3 2022-08-27 thomas sizeof(sock->conf.srv_name)) >= sizeof(sock->conf.srv_name)) {
232 9d7714e3 2022-08-27 thomas free(sock);
233 9d7714e3 2022-08-27 thomas fatalx("%s: strlcpy", __func__);
234 9d7714e3 2022-08-27 thomas }
235 9d7714e3 2022-08-27 thomas
236 9d7714e3 2022-08-27 thomas acp = &sock->conf.addr;
237 9d7714e3 2022-08-27 thomas
238 9d7714e3 2022-08-27 thomas memcpy(&acp->ss, &a->ss, sizeof(acp->ss));
239 2edd250d 2023-11-16 thomas acp->slen = a->slen;
240 7d1d4b6f 2023-11-16 thomas acp->ai_family = a->ai_family;
241 7d1d4b6f 2023-11-16 thomas acp->ai_socktype = a->ai_socktype;
242 7d1d4b6f 2023-11-16 thomas acp->ai_protocol = a->ai_protocol;
243 9d7714e3 2022-08-27 thomas acp->port = a->port;
244 102d840d 2023-06-22 thomas if (*a->ifname != '\0') {
245 9d7714e3 2022-08-27 thomas if (strlcpy(acp->ifname, a->ifname,
246 9d7714e3 2022-08-27 thomas sizeof(acp->ifname)) >= sizeof(acp->ifname)) {
247 9d7714e3 2022-08-27 thomas fatalx("%s: interface name truncated",
248 9d7714e3 2022-08-27 thomas __func__);
249 9d7714e3 2022-08-27 thomas }
250 720c2b05 2022-08-16 thomas }
251 720c2b05 2022-08-16 thomas
252 8a35f56c 2022-07-16 thomas return (sock);
253 8a35f56c 2022-07-16 thomas }
254 8a35f56c 2022-07-16 thomas
255 1f6ec068 2022-08-27 thomas static void
256 8a35f56c 2022-07-16 thomas sockets_launch(void)
257 8a35f56c 2022-07-16 thomas {
258 8a35f56c 2022-07-16 thomas struct socket *sock;
259 79e60db6 2023-11-14 thomas struct server *srv;
260 79e60db6 2023-11-14 thomas const struct got_error *error;
261 8a35f56c 2022-07-16 thomas
262 90d63d47 2022-08-16 thomas TAILQ_FOREACH(sock, &gotwebd_env->sockets, entry) {
263 8a35f56c 2022-07-16 thomas log_debug("%s: configuring socket %d (%d)", __func__,
264 8a35f56c 2022-07-16 thomas sock->conf.id, sock->fd);
265 8a35f56c 2022-07-16 thomas
266 8a35f56c 2022-07-16 thomas event_set(&sock->ev, sock->fd, EV_READ | EV_PERSIST,
267 8a35f56c 2022-07-16 thomas sockets_socket_accept, sock);
268 8a35f56c 2022-07-16 thomas
269 8a35f56c 2022-07-16 thomas if (event_add(&sock->ev, NULL))
270 8a35f56c 2022-07-16 thomas fatalx("event add sock");
271 8a35f56c 2022-07-16 thomas
272 8a35f56c 2022-07-16 thomas evtimer_set(&sock->pause, sockets_accept_paused, sock);
273 8a35f56c 2022-07-16 thomas
274 8a35f56c 2022-07-16 thomas log_debug("%s: running socket listener %d", __func__,
275 8a35f56c 2022-07-16 thomas sock->conf.id);
276 8a35f56c 2022-07-16 thomas }
277 79e60db6 2023-11-14 thomas
278 79e60db6 2023-11-14 thomas TAILQ_FOREACH(srv, &gotwebd_env->servers, entry) {
279 79e60db6 2023-11-14 thomas if (unveil(srv->repos_path, "r") == -1)
280 79e60db6 2023-11-14 thomas fatal("unveil %s", srv->repos_path);
281 79e60db6 2023-11-14 thomas }
282 79e60db6 2023-11-14 thomas
283 79e60db6 2023-11-14 thomas error = got_privsep_unveil_exec_helpers();
284 79e60db6 2023-11-14 thomas if (error)
285 79e60db6 2023-11-14 thomas fatal("%s", error->msg);
286 79e60db6 2023-11-14 thomas
287 79e60db6 2023-11-14 thomas if (unveil(NULL, NULL) == -1)
288 79e60db6 2023-11-14 thomas fatal("unveil");
289 8a35f56c 2022-07-16 thomas }
290 8a35f56c 2022-07-16 thomas
291 1f6ec068 2022-08-27 thomas static void
292 8a35f56c 2022-07-16 thomas sockets_purge(struct gotwebd *env)
293 8a35f56c 2022-07-16 thomas {
294 8a35f56c 2022-07-16 thomas struct socket *sock, *tsock;
295 8a35f56c 2022-07-16 thomas
296 8a35f56c 2022-07-16 thomas /* shutdown and remove sockets */
297 90d63d47 2022-08-16 thomas TAILQ_FOREACH_SAFE(sock, &env->sockets, entry, tsock) {
298 8a35f56c 2022-07-16 thomas if (event_initialized(&sock->ev))
299 8a35f56c 2022-07-16 thomas event_del(&sock->ev);
300 8a35f56c 2022-07-16 thomas if (evtimer_initialized(&sock->evt))
301 8a35f56c 2022-07-16 thomas evtimer_del(&sock->evt);
302 8a35f56c 2022-07-16 thomas if (evtimer_initialized(&sock->pause))
303 8a35f56c 2022-07-16 thomas evtimer_del(&sock->pause);
304 8a35f56c 2022-07-16 thomas if (sock->fd != -1)
305 8a35f56c 2022-07-16 thomas close(sock->fd);
306 90d63d47 2022-08-16 thomas TAILQ_REMOVE(&env->sockets, sock, entry);
307 8a35f56c 2022-07-16 thomas }
308 8a35f56c 2022-07-16 thomas }
309 8a35f56c 2022-07-16 thomas
310 f85c939f 2023-11-22 thomas static void
311 f85c939f 2023-11-22 thomas sockets_dispatch_main(int fd, short event, void *arg)
312 8a35f56c 2022-07-16 thomas {
313 f85c939f 2023-11-22 thomas struct imsgev *iev = arg;
314 f85c939f 2023-11-22 thomas struct imsgbuf *ibuf;
315 f85c939f 2023-11-22 thomas struct imsg imsg;
316 f85c939f 2023-11-22 thomas struct gotwebd *env = gotwebd_env;
317 f85c939f 2023-11-22 thomas ssize_t n;
318 f85c939f 2023-11-22 thomas int shut = 0;
319 8a35f56c 2022-07-16 thomas
320 f85c939f 2023-11-22 thomas ibuf = &iev->ibuf;
321 f85c939f 2023-11-22 thomas
322 f85c939f 2023-11-22 thomas if (event & EV_READ) {
323 f85c939f 2023-11-22 thomas if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
324 f85c939f 2023-11-22 thomas fatal("imsg_read error");
325 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
326 f85c939f 2023-11-22 thomas shut = 1;
327 8a35f56c 2022-07-16 thomas }
328 f85c939f 2023-11-22 thomas if (event & EV_WRITE) {
329 f85c939f 2023-11-22 thomas if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
330 f85c939f 2023-11-22 thomas fatal("msgbuf_write");
331 f85c939f 2023-11-22 thomas if (n == 0) /* Connection closed */
332 f85c939f 2023-11-22 thomas shut = 1;
333 f85c939f 2023-11-22 thomas }
334 8a35f56c 2022-07-16 thomas
335 f85c939f 2023-11-22 thomas for (;;) {
336 f85c939f 2023-11-22 thomas if ((n = imsg_get(ibuf, &imsg)) == -1)
337 f85c939f 2023-11-22 thomas fatal("imsg_get");
338 f85c939f 2023-11-22 thomas if (n == 0) /* No more messages. */
339 f85c939f 2023-11-22 thomas break;
340 f85c939f 2023-11-22 thomas
341 f85c939f 2023-11-22 thomas switch (imsg.hdr.type) {
342 f85c939f 2023-11-22 thomas case IMSG_CFG_SRV:
343 f85c939f 2023-11-22 thomas config_getserver(env, &imsg);
344 f85c939f 2023-11-22 thomas break;
345 f85c939f 2023-11-22 thomas case IMSG_CFG_SOCK:
346 f85c939f 2023-11-22 thomas config_getsock(env, &imsg);
347 f85c939f 2023-11-22 thomas break;
348 f85c939f 2023-11-22 thomas case IMSG_CFG_FD:
349 f85c939f 2023-11-22 thomas config_getfd(env, &imsg);
350 f85c939f 2023-11-22 thomas break;
351 f85c939f 2023-11-22 thomas case IMSG_CFG_DONE:
352 f85c939f 2023-11-22 thomas config_getcfg(env, &imsg);
353 f85c939f 2023-11-22 thomas break;
354 f85c939f 2023-11-22 thomas case IMSG_CTL_START:
355 f85c939f 2023-11-22 thomas sockets_launch();
356 f85c939f 2023-11-22 thomas break;
357 f85c939f 2023-11-22 thomas default:
358 f85c939f 2023-11-22 thomas fatalx("%s: unknown imsg type %d", __func__,
359 f85c939f 2023-11-22 thomas imsg.hdr.type);
360 f85c939f 2023-11-22 thomas }
361 f85c939f 2023-11-22 thomas
362 f85c939f 2023-11-22 thomas imsg_free(&imsg);
363 8a35f56c 2022-07-16 thomas }
364 8a35f56c 2022-07-16 thomas
365 f85c939f 2023-11-22 thomas if (!shut)
366 f85c939f 2023-11-22 thomas imsg_event_add(iev);
367 f85c939f 2023-11-22 thomas else {
368 f85c939f 2023-11-22 thomas /* This pipe is dead. Remove its event handler */
369 f85c939f 2023-11-22 thomas event_del(&iev->ev);
370 f85c939f 2023-11-22 thomas event_loopexit(NULL);
371 f85c939f 2023-11-22 thomas }
372 8a35f56c 2022-07-16 thomas }
373 8a35f56c 2022-07-16 thomas
374 1f6ec068 2022-08-27 thomas static void
375 8a35f56c 2022-07-16 thomas sockets_sighdlr(int sig, short event, void *arg)
376 8a35f56c 2022-07-16 thomas {
377 8a35f56c 2022-07-16 thomas switch (sig) {
378 8a35f56c 2022-07-16 thomas case SIGHUP:
379 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGHUP", __func__);
380 8a35f56c 2022-07-16 thomas break;
381 8a35f56c 2022-07-16 thomas case SIGPIPE:
382 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGPIPE", __func__);
383 8a35f56c 2022-07-16 thomas break;
384 8a35f56c 2022-07-16 thomas case SIGUSR1:
385 8a35f56c 2022-07-16 thomas log_info("%s: ignoring SIGUSR1", __func__);
386 8a35f56c 2022-07-16 thomas break;
387 8a35f56c 2022-07-16 thomas case SIGCHLD:
388 8a35f56c 2022-07-16 thomas break;
389 8a35f56c 2022-07-16 thomas default:
390 8a35f56c 2022-07-16 thomas log_info("SIGNAL: %d", sig);
391 8a35f56c 2022-07-16 thomas fatalx("unexpected signal");
392 8a35f56c 2022-07-16 thomas }
393 8a35f56c 2022-07-16 thomas }
394 8a35f56c 2022-07-16 thomas
395 f85c939f 2023-11-22 thomas static void
396 8a35f56c 2022-07-16 thomas sockets_shutdown(void)
397 8a35f56c 2022-07-16 thomas {
398 8a35f56c 2022-07-16 thomas struct server *srv, *tsrv;
399 8a35f56c 2022-07-16 thomas struct socket *sock, *tsock;
400 8a35f56c 2022-07-16 thomas
401 8a35f56c 2022-07-16 thomas sockets_purge(gotwebd_env);
402 8a35f56c 2022-07-16 thomas
403 8a35f56c 2022-07-16 thomas /* clean sockets */
404 90d63d47 2022-08-16 thomas TAILQ_FOREACH_SAFE(sock, &gotwebd_env->sockets, entry, tsock) {
405 90d63d47 2022-08-16 thomas TAILQ_REMOVE(&gotwebd_env->sockets, sock, entry);
406 8a35f56c 2022-07-16 thomas close(sock->fd);
407 8a35f56c 2022-07-16 thomas free(sock);
408 8a35f56c 2022-07-16 thomas }
409 8a35f56c 2022-07-16 thomas
410 8a35f56c 2022-07-16 thomas /* clean servers */
411 ab5bda7e 2023-11-22 thomas TAILQ_FOREACH_SAFE(srv, &gotwebd_env->servers, entry, tsrv)
412 8a35f56c 2022-07-16 thomas free(srv);
413 8a35f56c 2022-07-16 thomas
414 8a35f56c 2022-07-16 thomas free(gotwebd_env);
415 8a35f56c 2022-07-16 thomas }
416 8a35f56c 2022-07-16 thomas
417 8a35f56c 2022-07-16 thomas int
418 8a35f56c 2022-07-16 thomas sockets_privinit(struct gotwebd *env, struct socket *sock)
419 8a35f56c 2022-07-16 thomas {
420 720c2b05 2022-08-16 thomas if (sock->conf.af_type == AF_UNIX) {
421 8a35f56c 2022-07-16 thomas log_debug("%s: initializing unix socket %s", __func__,
422 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
423 f85c939f 2023-11-22 thomas sock->fd = sockets_unix_socket_listen(env, sock);
424 8a35f56c 2022-07-16 thomas if (sock->fd == -1) {
425 8a35f56c 2022-07-16 thomas log_warnx("%s: create unix socket failed", __func__);
426 8a35f56c 2022-07-16 thomas return -1;
427 8a35f56c 2022-07-16 thomas }
428 8a35f56c 2022-07-16 thomas }
429 8a35f56c 2022-07-16 thomas
430 720c2b05 2022-08-16 thomas if (sock->conf.af_type == AF_INET || sock->conf.af_type == AF_INET6) {
431 720c2b05 2022-08-16 thomas log_debug("%s: initializing %s FCGI socket on port %d for %s",
432 720c2b05 2022-08-16 thomas __func__, sock->conf.af_type == AF_INET ? "inet" : "inet6",
433 720c2b05 2022-08-16 thomas sock->conf.fcgi_socket_port, sock->conf.name);
434 7d1d4b6f 2023-11-16 thomas sock->fd = sockets_create_socket(&sock->conf.addr);
435 8a35f56c 2022-07-16 thomas if (sock->fd == -1) {
436 9d7714e3 2022-08-27 thomas log_warnx("%s: create FCGI socket failed", __func__);
437 8a35f56c 2022-07-16 thomas return -1;
438 8a35f56c 2022-07-16 thomas }
439 8a35f56c 2022-07-16 thomas }
440 8a35f56c 2022-07-16 thomas
441 8a35f56c 2022-07-16 thomas return 0;
442 8a35f56c 2022-07-16 thomas }
443 8a35f56c 2022-07-16 thomas
444 1f6ec068 2022-08-27 thomas static int
445 f85c939f 2023-11-22 thomas sockets_unix_socket_listen(struct gotwebd *env, struct socket *sock)
446 8a35f56c 2022-07-16 thomas {
447 8a35f56c 2022-07-16 thomas struct sockaddr_un sun;
448 8a35f56c 2022-07-16 thomas struct socket *tsock;
449 8a35f56c 2022-07-16 thomas int u_fd = -1;
450 8a35f56c 2022-07-16 thomas mode_t old_umask, mode;
451 8a35f56c 2022-07-16 thomas
452 90d63d47 2022-08-16 thomas TAILQ_FOREACH(tsock, &env->sockets, entry) {
453 8a35f56c 2022-07-16 thomas if (strcmp(tsock->conf.unix_socket_name,
454 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name) == 0 &&
455 8a35f56c 2022-07-16 thomas tsock->fd != -1)
456 8a35f56c 2022-07-16 thomas return (tsock->fd);
457 8a35f56c 2022-07-16 thomas }
458 8a35f56c 2022-07-16 thomas
459 dd7a7d5b 2022-07-16 thomas /* TA: FIXME: this needs upstreaming. */
460 dd7a7d5b 2022-07-16 thomas int socket_flags = SOCK_STREAM | SOCK_NONBLOCK;
461 dd7a7d5b 2022-07-16 thomas #ifdef SOCK_CLOEXEC
462 dd7a7d5b 2022-07-16 thomas socket_flags |= SOCK_CLOEXEC;
463 dd7a7d5b 2022-07-16 thomas #endif
464 dd7a7d5b 2022-07-16 thomas u_fd = socket(AF_UNIX, socket_flags, 0);
465 8a35f56c 2022-07-16 thomas if (u_fd == -1) {
466 8a35f56c 2022-07-16 thomas log_warn("%s: socket", __func__);
467 8a35f56c 2022-07-16 thomas return -1;
468 8a35f56c 2022-07-16 thomas }
469 8a35f56c 2022-07-16 thomas
470 8a35f56c 2022-07-16 thomas sun.sun_family = AF_UNIX;
471 8a35f56c 2022-07-16 thomas if (strlcpy(sun.sun_path, sock->conf.unix_socket_name,
472 8a35f56c 2022-07-16 thomas sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
473 8a35f56c 2022-07-16 thomas log_warn("%s: %s name too long", __func__,
474 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
475 8a35f56c 2022-07-16 thomas close(u_fd);
476 8a35f56c 2022-07-16 thomas return -1;
477 8a35f56c 2022-07-16 thomas }
478 8a35f56c 2022-07-16 thomas
479 8a35f56c 2022-07-16 thomas if (unlink(sock->conf.unix_socket_name) == -1) {
480 8a35f56c 2022-07-16 thomas if (errno != ENOENT) {
481 8a35f56c 2022-07-16 thomas log_warn("%s: unlink %s", __func__,
482 8a35f56c 2022-07-16 thomas sock->conf.unix_socket_name);
483 8a35f56c 2022-07-16 thomas close(u_fd);
484 8a35f56c 2022-07-16 thomas return -1;
485 8a35f56c 2022-07-16 thomas }
486 8a35f56c 2022-07-16 thomas }
487 8a35f56c 2022-07-16 thomas
488 8a35f56c 2022-07-16 thomas old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
489 8a35f56c 2022-07-16 thomas mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
490 8a35f56c 2022-07-16 thomas
491 8a35f56c 2022-07-16 thomas if (bind(u_fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
492 8a35f56c 2022-07-16 thomas log_warn("%s: bind: %s", __func__, sock->conf.unix_socket_name);
493 8a35f56c 2022-07-16 thomas close(u_fd);
494 8a35f56c 2022-07-16 thomas (void)umask(old_umask);
495 8a35f56c 2022-07-16 thomas return -1;
496 8a35f56c 2022-07-16 thomas }
497 8a35f56c 2022-07-16 thomas
498 8a35f56c 2022-07-16 thomas (void)umask(old_umask);
499 8a35f56c 2022-07-16 thomas
500 8a35f56c 2022-07-16 thomas if (chmod(sock->conf.unix_socket_name, mode) == -1) {
501 8a35f56c 2022-07-16 thomas log_warn("%s: chmod", __func__);
502 8a35f56c 2022-07-16 thomas close(u_fd);
503 8a35f56c 2022-07-16 thomas (void)unlink(sock->conf.unix_socket_name);
504 8a35f56c 2022-07-16 thomas return -1;
505 8a35f56c 2022-07-16 thomas }
506 8a35f56c 2022-07-16 thomas
507 f85c939f 2023-11-22 thomas if (chown(sock->conf.unix_socket_name, env->pw->pw_uid,
508 f85c939f 2023-11-22 thomas env->pw->pw_gid) == -1) {
509 8a35f56c 2022-07-16 thomas log_warn("%s: chown", __func__);
510 8a35f56c 2022-07-16 thomas close(u_fd);
511 8a35f56c 2022-07-16 thomas (void)unlink(sock->conf.unix_socket_name);
512 8a35f56c 2022-07-16 thomas return -1;
513 8a35f56c 2022-07-16 thomas }
514 8a35f56c 2022-07-16 thomas
515 8a35f56c 2022-07-16 thomas if (listen(u_fd, SOCKS_BACKLOG) == -1) {
516 8a35f56c 2022-07-16 thomas log_warn("%s: listen", __func__);
517 8a35f56c 2022-07-16 thomas return -1;
518 8a35f56c 2022-07-16 thomas }
519 8a35f56c 2022-07-16 thomas
520 8a35f56c 2022-07-16 thomas return u_fd;
521 8a35f56c 2022-07-16 thomas }
522 8a35f56c 2022-07-16 thomas
523 1f6ec068 2022-08-27 thomas static int
524 7d1d4b6f 2023-11-16 thomas sockets_create_socket(struct address *a)
525 8a35f56c 2022-07-16 thomas {
526 8a35f56c 2022-07-16 thomas int fd = -1, o_val = 1, flags;
527 8a35f56c 2022-07-16 thomas
528 7d1d4b6f 2023-11-16 thomas fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
529 9d7714e3 2022-08-27 thomas if (fd == -1)
530 9d7714e3 2022-08-27 thomas return -1;
531 8a35f56c 2022-07-16 thomas
532 9d7714e3 2022-08-27 thomas log_debug("%s: opened socket (%d) for %s", __func__,
533 9d7714e3 2022-08-27 thomas fd, a->ifname);
534 8a35f56c 2022-07-16 thomas
535 9d7714e3 2022-08-27 thomas if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &o_val,
536 9d7714e3 2022-08-27 thomas sizeof(int)) == -1) {
537 9d7714e3 2022-08-27 thomas log_warn("%s: setsockopt error", __func__);
538 9d7714e3 2022-08-27 thomas close(fd);
539 9d7714e3 2022-08-27 thomas return -1;
540 9d7714e3 2022-08-27 thomas }
541 8a35f56c 2022-07-16 thomas
542 9d7714e3 2022-08-27 thomas /* non-blocking */
543 9d7714e3 2022-08-27 thomas flags = fcntl(fd, F_GETFL);
544 9d7714e3 2022-08-27 thomas flags |= O_NONBLOCK;
545 9d7714e3 2022-08-27 thomas if (fcntl(fd, F_SETFL, flags) == -1) {
546 9d7714e3 2022-08-27 thomas log_info("%s: could not enable non-blocking I/O", __func__);
547 9d7714e3 2022-08-27 thomas close(fd);
548 9d7714e3 2022-08-27 thomas return -1;
549 9d7714e3 2022-08-27 thomas }
550 8a35f56c 2022-07-16 thomas
551 2edd250d 2023-11-16 thomas if (bind(fd, (struct sockaddr *)&a->ss, a->slen) == -1) {
552 9d7714e3 2022-08-27 thomas close(fd);
553 7d1d4b6f 2023-11-16 thomas log_info("%s: can't bind to port %d", __func__, a->port);
554 9d7714e3 2022-08-27 thomas return -1;
555 8a35f56c 2022-07-16 thomas }
556 8a35f56c 2022-07-16 thomas
557 9d7714e3 2022-08-27 thomas if (listen(fd, SOMAXCONN) == -1) {
558 9d7714e3 2022-08-27 thomas log_warn("%s, unable to listen on socket", __func__);
559 9d7714e3 2022-08-27 thomas close(fd);
560 9d7714e3 2022-08-27 thomas return -1;
561 9d7714e3 2022-08-27 thomas }
562 9d7714e3 2022-08-27 thomas
563 8a35f56c 2022-07-16 thomas return (fd);
564 8a35f56c 2022-07-16 thomas }
565 8a35f56c 2022-07-16 thomas
566 1f6ec068 2022-08-27 thomas static int
567 8a35f56c 2022-07-16 thomas sockets_accept_reserve(int sockfd, struct sockaddr *addr, socklen_t *addrlen,
568 8a35f56c 2022-07-16 thomas int reserve, volatile int *counter)
569 8a35f56c 2022-07-16 thomas {
570 8a35f56c 2022-07-16 thomas int ret;
571 8a35f56c 2022-07-16 thomas
572 8a35f56c 2022-07-16 thomas if (getdtablecount() + reserve +
573 8a35f56c 2022-07-16 thomas ((*counter + 1) * FD_NEEDED) >= getdtablesize()) {
574 8a35f56c 2022-07-16 thomas log_debug("inflight fds exceeded");
575 8a35f56c 2022-07-16 thomas errno = EMFILE;
576 8a35f56c 2022-07-16 thomas return -1;
577 8a35f56c 2022-07-16 thomas }
578 5ae43732 2022-07-16 thomas /* TA: This needs fixing upstream. */
579 5ae43732 2022-07-16 thomas #ifdef __APPLE__
580 5ae43732 2022-07-16 thomas ret = accept(sockfd, addr, addrlen);
581 5ae43732 2022-07-16 thomas #else
582 5ae43732 2022-07-16 thomas ret = accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
583 5ae43732 2022-07-16 thomas #endif
584 8a35f56c 2022-07-16 thomas
585 5ae43732 2022-07-16 thomas if (ret > -1) {
586 8a35f56c 2022-07-16 thomas (*counter)++;
587 8a35f56c 2022-07-16 thomas log_debug("inflight incremented, now %d", *counter);
588 8a35f56c 2022-07-16 thomas }
589 8a35f56c 2022-07-16 thomas
590 8a35f56c 2022-07-16 thomas return ret;
591 8a35f56c 2022-07-16 thomas }
592 8a35f56c 2022-07-16 thomas
593 1f6ec068 2022-08-27 thomas static void
594 8a35f56c 2022-07-16 thomas sockets_accept_paused(int fd, short events, void *arg)
595 8a35f56c 2022-07-16 thomas {
596 8a35f56c 2022-07-16 thomas struct socket *sock = (struct socket *)arg;
597 8a35f56c 2022-07-16 thomas
598 8a35f56c 2022-07-16 thomas event_add(&sock->ev, NULL);
599 8a35f56c 2022-07-16 thomas }
600 8a35f56c 2022-07-16 thomas
601 8a35f56c 2022-07-16 thomas void
602 8a35f56c 2022-07-16 thomas sockets_socket_accept(int fd, short event, void *arg)
603 8a35f56c 2022-07-16 thomas {
604 8a35f56c 2022-07-16 thomas struct socket *sock = (struct socket *)arg;
605 8a35f56c 2022-07-16 thomas struct sockaddr_storage ss;
606 8a35f56c 2022-07-16 thomas struct timeval backoff;
607 8a35f56c 2022-07-16 thomas struct request *c = NULL;
608 8a35f56c 2022-07-16 thomas socklen_t len;
609 8a35f56c 2022-07-16 thomas int s;
610 8a35f56c 2022-07-16 thomas
611 8a35f56c 2022-07-16 thomas backoff.tv_sec = 1;
612 8a35f56c 2022-07-16 thomas backoff.tv_usec = 0;
613 8a35f56c 2022-07-16 thomas
614 8a35f56c 2022-07-16 thomas event_add(&sock->ev, NULL);
615 8a35f56c 2022-07-16 thomas if (event & EV_TIMEOUT)
616 8a35f56c 2022-07-16 thomas return;
617 8a35f56c 2022-07-16 thomas
618 8a35f56c 2022-07-16 thomas len = sizeof(ss);
619 8a35f56c 2022-07-16 thomas
620 8a35f56c 2022-07-16 thomas s = sockets_accept_reserve(fd, (struct sockaddr *)&ss, &len,
621 8a35f56c 2022-07-16 thomas FD_RESERVE, &cgi_inflight);
622 8a35f56c 2022-07-16 thomas
623 8a35f56c 2022-07-16 thomas if (s == -1) {
624 8a35f56c 2022-07-16 thomas switch (errno) {
625 8a35f56c 2022-07-16 thomas case EINTR:
626 8a35f56c 2022-07-16 thomas case EWOULDBLOCK:
627 8a35f56c 2022-07-16 thomas case ECONNABORTED:
628 8a35f56c 2022-07-16 thomas return;
629 8a35f56c 2022-07-16 thomas case EMFILE:
630 8a35f56c 2022-07-16 thomas case ENFILE:
631 8a35f56c 2022-07-16 thomas event_del(&sock->ev);
632 8a35f56c 2022-07-16 thomas evtimer_add(&sock->pause, &backoff);
633 8a35f56c 2022-07-16 thomas return;
634 8a35f56c 2022-07-16 thomas default:
635 8a35f56c 2022-07-16 thomas log_warn("%s: accept", __func__);
636 8a35f56c 2022-07-16 thomas }
637 8a35f56c 2022-07-16 thomas }
638 8a35f56c 2022-07-16 thomas
639 8a35f56c 2022-07-16 thomas if (client_cnt > GOTWEBD_MAXCLIENTS)
640 8a35f56c 2022-07-16 thomas goto err;
641 8a35f56c 2022-07-16 thomas
642 8a35f56c 2022-07-16 thomas c = calloc(1, sizeof(struct request));
643 8a35f56c 2022-07-16 thomas if (c == NULL) {
644 e7e5fa49 2022-12-30 thomas log_warn("%s", __func__);
645 e7e5fa49 2022-12-30 thomas close(s);
646 e7e5fa49 2022-12-30 thomas cgi_inflight--;
647 e7e5fa49 2022-12-30 thomas return;
648 e7e5fa49 2022-12-30 thomas }
649 e7e5fa49 2022-12-30 thomas
650 d8bf4f25 2023-09-14 thomas c->tp = template(c, &fcgi_write, c->outbuf, sizeof(c->outbuf));
651 e7e5fa49 2022-12-30 thomas if (c->tp == NULL) {
652 8a35f56c 2022-07-16 thomas log_warn("%s", __func__);
653 8a35f56c 2022-07-16 thomas close(s);
654 8a35f56c 2022-07-16 thomas cgi_inflight--;
655 e7e5fa49 2022-12-30 thomas free(c);
656 8a35f56c 2022-07-16 thomas return;
657 8a35f56c 2022-07-16 thomas }
658 8a35f56c 2022-07-16 thomas
659 8a35f56c 2022-07-16 thomas c->fd = s;
660 8a35f56c 2022-07-16 thomas c->sock = sock;
661 8a35f56c 2022-07-16 thomas memcpy(c->priv_fd, sock->priv_fd, sizeof(c->priv_fd));
662 8a35f56c 2022-07-16 thomas c->buf_pos = 0;
663 8a35f56c 2022-07-16 thomas c->buf_len = 0;
664 8a35f56c 2022-07-16 thomas c->request_started = 0;
665 8a35f56c 2022-07-16 thomas c->sock->client_status = CLIENT_CONNECT;
666 8a35f56c 2022-07-16 thomas
667 2e9bd5cb 2023-03-10 thomas event_set(&c->ev, s, EV_READ|EV_PERSIST, fcgi_request, c);
668 8a35f56c 2022-07-16 thomas event_add(&c->ev, NULL);
669 8a35f56c 2022-07-16 thomas
670 8a35f56c 2022-07-16 thomas evtimer_set(&c->tmo, fcgi_timeout, c);
671 8a35f56c 2022-07-16 thomas evtimer_add(&c->tmo, &timeout);
672 8a35f56c 2022-07-16 thomas
673 8a35f56c 2022-07-16 thomas client_cnt++;
674 8a35f56c 2022-07-16 thomas
675 8a35f56c 2022-07-16 thomas return;
676 8a35f56c 2022-07-16 thomas err:
677 8a35f56c 2022-07-16 thomas cgi_inflight--;
678 8a35f56c 2022-07-16 thomas close(s);
679 8a35f56c 2022-07-16 thomas if (c != NULL)
680 8a35f56c 2022-07-16 thomas free(c);
681 8a35f56c 2022-07-16 thomas }
682 8a35f56c 2022-07-16 thomas
683 1f6ec068 2022-08-27 thomas static void
684 8a35f56c 2022-07-16 thomas sockets_rlimit(int maxfd)
685 8a35f56c 2022-07-16 thomas {
686 8a35f56c 2022-07-16 thomas struct rlimit rl;
687 8a35f56c 2022-07-16 thomas
688 8a35f56c 2022-07-16 thomas if (getrlimit(RLIMIT_NOFILE, &rl) == -1)
689 8a35f56c 2022-07-16 thomas fatal("%s: failed to get resource limit", __func__);
690 ceac46c9 2022-07-17 thomas log_debug("%s: max open files %llu", __func__,
691 ceac46c9 2022-07-17 thomas (unsigned long long)rl.rlim_max);
692 8a35f56c 2022-07-16 thomas
693 8a35f56c 2022-07-16 thomas /*
694 8a35f56c 2022-07-16 thomas * Allow the maximum number of open file descriptors for this
695 8a35f56c 2022-07-16 thomas * login class (which should be the class "daemon" by default).
696 8a35f56c 2022-07-16 thomas */
697 8a35f56c 2022-07-16 thomas if (maxfd == -1)
698 8a35f56c 2022-07-16 thomas rl.rlim_cur = rl.rlim_max;
699 8a35f56c 2022-07-16 thomas else
700 8a35f56c 2022-07-16 thomas rl.rlim_cur = MAXIMUM(rl.rlim_max, (rlim_t)maxfd);
701 8a35f56c 2022-07-16 thomas if (setrlimit(RLIMIT_NOFILE, &rl) == -1)
702 8a35f56c 2022-07-16 thomas fatal("%s: failed to set resource limit", __func__);
703 ff36aeea 2022-07-16 thomas }