Blob


1 /*
2 * Copyright (c) 2020-2021 Tracey Emery <tracey@traceyemery.net>
3 * Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
18 #include <sys/types.h>
19 #include <sys/queue.h>
20 #include <sys/time.h>
21 #include <sys/uio.h>
22 #include <sys/socket.h>
24 #include <net/if.h>
25 #include <netinet/in.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <termios.h>
30 #include <unistd.h>
31 #include <limits.h>
32 #include <string.h>
33 #include <event.h>
34 #include <fcntl.h>
35 #include <errno.h>
37 #include "got_opentemp.h"
38 #include "got_reference.h"
40 #include "gotwebd.h"
42 int
43 config_init(struct gotwebd *env)
44 {
45 strlcpy(env->httpd_chroot, D_HTTPD_CHROOT, sizeof(env->httpd_chroot));
47 env->prefork_gotwebd = GOTWEBD_NUMPROC;
48 env->server_cnt = 0;
49 TAILQ_INIT(&env->servers);
50 TAILQ_INIT(&env->sockets);
52 return 0;
53 }
55 int
56 config_getcfg(struct gotwebd *env, struct imsg *imsg)
57 {
58 /* nothing to do but tell gotwebd configuration is done */
59 if (sockets_compose_main(env, IMSG_CFG_DONE, NULL, 0) == -1)
60 fatal("sockets_compose_main IMSG_CFG_DONE");
61 return 0;
62 }
64 int
65 config_setserver(struct gotwebd *env, struct server *srv)
66 {
67 if (main_compose_sockets(env, IMSG_CFG_SRV, -1, srv, sizeof(*srv))
68 == -1)
69 fatal("main_compose_sockets IMSG_CFG_SRV");
70 return 0;
71 }
73 int
74 config_getserver(struct gotwebd *env, struct imsg *imsg)
75 {
76 struct server *srv;
77 uint8_t *p = imsg->data;
79 srv = calloc(1, sizeof(*srv));
80 if (srv == NULL)
81 fatalx("%s: calloc", __func__);
83 IMSG_SIZE_CHECK(imsg, srv);
85 memcpy(srv, p, sizeof(*srv));
86 srv->cached_repos = calloc(GOTWEBD_REPO_CACHESIZE,
87 sizeof(*srv->cached_repos));
88 if (srv->cached_repos == NULL)
89 fatal("%s: calloc", __func__);
90 srv->ncached_repos = 0;
92 /* log server info */
93 log_debug("%s: server=%s fcgi_socket=%s unix_socket=%s", __func__,
94 srv->name, srv->fcgi_socket ? "yes" : "no", srv->unix_socket ?
95 "yes" : "no");
97 TAILQ_INSERT_TAIL(&env->servers, srv, entry);
99 return 0;
102 int
103 config_setsock(struct gotwebd *env, struct socket *sock)
105 /* open listening sockets */
106 if (sockets_privinit(env, sock) == -1)
107 return -1;
109 if (main_compose_sockets(env, IMSG_CFG_SOCK, sock->fd,
110 &sock->conf, sizeof(sock->conf)) == -1)
111 fatal("main_compose_sockets IMSG_CFG_SOCK");
113 sock->fd = -1;
114 return 0;
117 int
118 config_getsock(struct gotwebd *env, struct imsg *imsg)
120 struct socket *sock = NULL;
121 struct socket_conf sock_conf;
122 uint8_t *p = imsg->data;
123 int i;
125 IMSG_SIZE_CHECK(imsg, &sock_conf);
126 memcpy(&sock_conf, p, sizeof(sock_conf));
128 if (IMSG_DATA_SIZE(imsg) != sizeof(sock_conf)) {
129 log_debug("%s: imsg size error", __func__);
130 return 1;
133 /* create a new socket */
134 if ((sock = calloc(1, sizeof(*sock))) == NULL) {
135 if (imsg->fd != -1)
136 close(imsg->fd);
137 return 1;
140 memcpy(&sock->conf, &sock_conf, sizeof(sock->conf));
141 sock->fd = imsg->fd;
143 TAILQ_INSERT_TAIL(&env->sockets, sock, entry);
145 for (i = 0; i < PRIV_FDS__MAX; i++)
146 sock->priv_fd[i] = -1;
148 for (i = 0; i < GOTWEB_PACK_NUM_TEMPFILES; i++)
149 sock->pack_fds[i] = -1;
151 /* log new socket info */
152 log_debug("%s: name=%s id=%d server=%s af_type=%s socket_path=%s",
153 __func__, sock->conf.name, sock->conf.id, sock->conf.srv_name,
154 sock->conf.af_type == AF_UNIX ? "unix" :
155 (sock->conf.af_type == AF_INET ? "inet" :
156 (sock->conf.af_type == AF_INET6 ? "inet6" : "unknown")),
157 *sock->conf.unix_socket_name != '\0' ?
158 sock->conf.unix_socket_name : "none");
160 return 0;
163 int
164 config_setfd(struct gotwebd *env, struct socket *sock)
166 int i, j, ret, fd;
168 log_debug("%s: Allocating %d file descriptors",
169 __func__, PRIV_FDS__MAX + GOTWEB_PACK_NUM_TEMPFILES);
171 for (i = 0; i < PRIV_FDS__MAX + GOTWEB_PACK_NUM_TEMPFILES; i++) {
172 for (j = 0; j < env->nserver; ++j) {
173 fd = got_opentempfd();
174 if (fd == -1)
175 fatal("got_opentemp");
176 if (imsg_compose_event(&env->iev_server[j],
177 IMSG_CFG_FD, 0, -1, fd, &sock->conf.id,
178 sizeof(sock->conf.id)) == -1)
179 fatal("imsg_compose_event IMSG_CFG_FD");
181 do {
182 ret = imsg_flush(&env->iev_server[j].ibuf);
183 } while (ret == -1 && errno == EAGAIN);
184 if (ret == -1)
185 fatal("imsg_flush");
186 imsg_event_add(&env->iev_server[j]);
190 return 0;
193 int
194 config_getfd(struct gotwebd *env, struct imsg *imsg)
196 struct socket *sock;
197 uint8_t *p = imsg->data;
198 int sock_id, match = 0, i;
200 IMSG_SIZE_CHECK(imsg, &sock_id);
201 memcpy(&sock_id, p, sizeof(sock_id));
203 TAILQ_FOREACH(sock, &env->sockets, entry) {
204 const int nfds = (GOTWEB_PACK_NUM_TEMPFILES + PRIV_FDS__MAX);
205 for (i = 0; i < nfds; i++) {
206 if (i < PRIV_FDS__MAX && sock->priv_fd[i] == -1) {
207 log_debug("%s: assigning socket %d priv_fd %d",
208 __func__, sock_id, imsg->fd);
209 sock->priv_fd[i] = imsg->fd;
210 match = 1;
211 break;
213 if (sock->pack_fds[i - PRIV_FDS__MAX] == -1) {
214 log_debug("%s: assigning socket %d pack_fd %d",
215 __func__, sock_id, imsg->fd);
216 sock->pack_fds[i - PRIV_FDS__MAX] = imsg->fd;
217 match = 1;
218 break;
223 if (match)
224 return 0;
225 else
226 return 1;