File: | src/usr.sbin/ldapd/control.c |
Warning: | line 237, column 7 Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: control.c,v 1.18 2023/03/08 04:43:13 guenther Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2010 Martin Hedenfalk <martin@bzero.se> |
5 | * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> |
6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. |
10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | */ |
19 | |
20 | #include <sys/queue.h> |
21 | #include <sys/types.h> |
22 | #include <sys/stat.h> |
23 | #include <sys/socket.h> |
24 | #include <sys/un.h> |
25 | #include <sys/tree.h> |
26 | |
27 | #include <net/if.h> |
28 | |
29 | #include <errno(*__errno()).h> |
30 | #include <event.h> |
31 | #include <fcntl.h> |
32 | #include <signal.h> |
33 | #include <stdlib.h> |
34 | #include <string.h> |
35 | #include <unistd.h> |
36 | |
37 | #include "ldapd.h" |
38 | #include "log.h" |
39 | |
40 | #define CONTROL_BACKLOG5 5 |
41 | |
42 | struct ctl_connlist ctl_conns = TAILQ_HEAD_INITIALIZER(ctl_conns){ ((void *)0), &(ctl_conns).tqh_first }; |
43 | |
44 | struct ctl_conn *control_connbyfd(int); |
45 | void control_close(int, struct control_sock *); |
46 | static void control_imsgev(struct imsgev *iev, int code, struct imsg *imsg); |
47 | static void control_needfd(struct imsgev *iev); |
48 | |
49 | void |
50 | control_init(struct control_sock *cs) |
51 | { |
52 | struct sockaddr_un sun; |
53 | int fd; |
54 | mode_t old_umask, mode; |
55 | |
56 | if (cs->cs_name == NULL((void *)0)) |
57 | return; |
58 | |
59 | if ((fd = socket(AF_UNIX1, SOCK_STREAM1 | SOCK_NONBLOCK0x4000, 0)) == -1) |
60 | fatal("control_init: socket"); |
61 | |
62 | memset(&sun, 0, sizeof(sun)); |
63 | sun.sun_family = AF_UNIX1; |
64 | if (strlcpy(sun.sun_path, cs->cs_name, |
65 | sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) |
66 | fatalx("control_init: name too long"); |
67 | |
68 | if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) |
69 | fatalx("control socket already listening"); |
70 | |
71 | if (unlink(cs->cs_name) == -1 && errno(*__errno()) != ENOENT2) |
72 | fatal("control_init: unlink"); |
73 | |
74 | if (cs->cs_restricted) { |
75 | old_umask = umask(S_IXUSR0000100|S_IXGRP0000010|S_IXOTH0000001); |
76 | mode = S_IRUSR0000400|S_IWUSR0000200|S_IRGRP0000040|S_IWGRP0000020|S_IROTH0000004|S_IWOTH0000002; |
77 | } else { |
78 | old_umask = umask(S_IXUSR0000100|S_IXGRP0000010|S_IWOTH0000002|S_IROTH0000004|S_IXOTH0000001); |
79 | mode = S_IRUSR0000400|S_IWUSR0000200|S_IRGRP0000040|S_IWGRP0000020; |
80 | } |
81 | |
82 | if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { |
83 | (void)umask(old_umask); |
84 | fatal("control_init: bind"); |
85 | } |
86 | (void)umask(old_umask); |
87 | |
88 | if (chmod(cs->cs_name, mode) == -1) { |
89 | (void)unlink(cs->cs_name); |
90 | fatal("control_init: chmod"); |
91 | } |
92 | |
93 | cs->cs_fd = fd; |
94 | } |
95 | |
96 | void |
97 | control_listen(struct control_sock *cs) |
98 | { |
99 | if (cs->cs_name == NULL((void *)0)) |
100 | return; |
101 | |
102 | if (listen(cs->cs_fd, CONTROL_BACKLOG5) == -1) |
103 | fatal("control_listen: listen"); |
104 | |
105 | event_set(&cs->cs_ev, cs->cs_fd, EV_READ0x02, |
106 | control_accept, cs); |
107 | event_add(&cs->cs_ev, NULL((void *)0)); |
108 | evtimer_set(&cs->cs_evt, control_accept, cs)event_set(&cs->cs_evt, -1, 0, control_accept, cs); |
109 | } |
110 | |
111 | void |
112 | control_cleanup(struct control_sock *cs) |
113 | { |
114 | if (cs->cs_name == NULL((void *)0)) |
115 | return; |
116 | event_del(&cs->cs_ev); |
117 | event_del(&cs->cs_evt); |
118 | } |
119 | |
120 | void |
121 | control_accept(int listenfd, short event, void *arg) |
122 | { |
123 | struct control_sock *cs = arg; |
124 | int connfd; |
125 | socklen_t len; |
126 | struct sockaddr_un sun; |
127 | struct ctl_conn *c; |
128 | |
129 | event_add(&cs->cs_ev, NULL((void *)0)); |
130 | if ((event & EV_TIMEOUT0x01)) |
131 | return; |
132 | |
133 | len = sizeof(sun); |
134 | if ((connfd = accept_reserve(listenfd, |
135 | (struct sockaddr *)&sun, &len, FD_RESERVE8)) == -1) { |
136 | /* |
137 | * Pause accept if we are out of file descriptors, or |
138 | * libevent will haunt us here too. |
139 | */ |
140 | if (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24) { |
141 | struct timeval evtpause = { 1, 0 }; |
142 | |
143 | event_del(&cs->cs_ev); |
144 | evtimer_add(&cs->cs_evt, &evtpause)event_add(&cs->cs_evt, &evtpause); |
145 | } else if (errno(*__errno()) != EWOULDBLOCK35 && errno(*__errno()) != EINTR4) |
146 | log_warn("control_accept"); |
147 | return; |
148 | } |
149 | |
150 | if ((c = calloc(1, sizeof(*c))) == NULL((void *)0)) { |
151 | log_warn("control_accept"); |
152 | close(connfd); |
153 | return; |
154 | } |
155 | |
156 | log_debug("accepted control fd %d", connfd); |
157 | TAILQ_INSERT_TAIL(&ctl_conns, c, entry)do { (c)->entry.tqe_next = ((void *)0); (c)->entry.tqe_prev = (&ctl_conns)->tqh_last; *(&ctl_conns)->tqh_last = (c); (&ctl_conns)->tqh_last = &(c)->entry.tqe_next ; } while (0); |
158 | imsgev_init(&c->iev, connfd, cs, control_imsgev, control_needfd); |
159 | } |
160 | |
161 | struct ctl_conn * |
162 | control_connbyfd(int fd) |
163 | { |
164 | struct ctl_conn *c; |
165 | |
166 | TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void *)0 ); (c) = ((c)->entry.tqe_next)) { |
167 | if (c->iev.ibuf.fd == fd) |
168 | break; |
169 | } |
170 | |
171 | return (c); |
172 | } |
173 | |
174 | void |
175 | control_close(int fd, struct control_sock *cs) |
176 | { |
177 | struct ctl_conn *c; |
178 | |
179 | if ((c = control_connbyfd(fd)) == NULL((void *)0)) { |
180 | log_warnx("control_close: fd %d: not found", fd); |
181 | return; |
182 | } |
183 | |
184 | log_debug("close control fd %d", c->iev.ibuf.fd); |
185 | TAILQ_REMOVE(&ctl_conns, c, entry)do { if (((c)->entry.tqe_next) != ((void *)0)) (c)->entry .tqe_next->entry.tqe_prev = (c)->entry.tqe_prev; else ( &ctl_conns)->tqh_last = (c)->entry.tqe_prev; *(c)-> entry.tqe_prev = (c)->entry.tqe_next; ; ; } while (0); |
186 | imsgev_clear(&c->iev); |
187 | |
188 | /* Some file descriptors are available again. */ |
189 | if (evtimer_pending(&cs->cs_evt, NULL)event_pending(&cs->cs_evt, 0x01, ((void *)0))) { |
190 | evtimer_del(&cs->cs_evt)event_del(&cs->cs_evt); |
191 | event_add(&cs->cs_ev, NULL((void *)0)); |
192 | } |
193 | |
194 | free(c); |
195 | } |
196 | |
197 | static int |
198 | send_stats(struct imsgev *iev) |
199 | { |
200 | struct namespace *ns; |
201 | const struct btree_stat *st; |
202 | struct ns_stat nss; |
203 | |
204 | imsgev_compose(iev, IMSG_CTL_STATS, 0, iev->ibuf.pid, -1, |
205 | &stats, sizeof(stats)); |
206 | |
207 | TAILQ_FOREACH(ns, &conf->namespaces, next)for((ns) = ((&conf->namespaces)->tqh_first); (ns) != ((void *)0); (ns) = ((ns)->next.tqe_next)) { |
208 | if (namespace_has_referrals(ns)) |
209 | continue; |
210 | memset(&nss, 0, sizeof(nss)); |
211 | strlcpy(nss.suffix, ns->suffix, sizeof(nss.suffix)); |
212 | if ((st = btree_stat(ns->data_db)) != NULL((void *)0)) |
213 | bcopy(st, &nss.data_stat, sizeof(nss.data_stat)); |
214 | |
215 | if ((st = btree_stat(ns->indx_db)) != NULL((void *)0)) |
216 | bcopy(st, &nss.indx_stat, sizeof(nss.indx_stat)); |
217 | |
218 | imsgev_compose(iev, IMSG_CTL_NSSTATS, 0, iev->ibuf.pid, -1, |
219 | &nss, sizeof(nss)); |
220 | } |
221 | |
222 | imsgev_compose(iev, IMSG_CTL_END, 0, iev->ibuf.pid, -1, NULL((void *)0), 0); |
223 | |
224 | return 0; |
225 | } |
226 | |
227 | static void |
228 | control_imsgev(struct imsgev *iev, int code, struct imsg *imsg) |
229 | { |
230 | struct control_sock *cs; |
231 | struct ctl_conn *c; |
232 | int fd, verbose; |
233 | |
234 | cs = iev->data; |
235 | fd = iev->ibuf.fd; |
236 | |
237 | if ((c = control_connbyfd(fd)) == NULL((void *)0)) { |
Although the value stored to 'c' is used in the enclosing expression, the value is never actually read from 'c' | |
238 | log_warnx("%s: fd %d: not found", __func__, fd); |
239 | return; |
240 | } |
241 | |
242 | if (code != IMSGEV_IMSG0) { |
243 | control_close(fd, cs); |
244 | return; |
245 | } |
246 | |
247 | log_debug("%s: got imsg %d on fd %d", __func__, imsg->hdr.type, fd); |
248 | switch (imsg->hdr.type) { |
249 | case IMSG_CTL_STATS: |
250 | if (send_stats(iev) == -1) { |
251 | log_debug("%s: failed to send statistics", __func__); |
252 | control_close(fd, cs); |
253 | } |
254 | break; |
255 | case IMSG_CTL_LOG_VERBOSE: |
256 | if (imsg->hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(verbose)) |
257 | break; |
258 | |
259 | bcopy(imsg->data, &verbose, sizeof(verbose)); |
260 | imsgev_compose(iev_ldapd, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, |
261 | &verbose, sizeof(verbose)); |
262 | |
263 | log_setverbose(verbose); |
264 | break; |
265 | default: |
266 | log_warnx("%s: unexpected imsg %d", __func__, imsg->hdr.type); |
267 | break; |
268 | } |
269 | } |
270 | |
271 | void |
272 | control_needfd(struct imsgev *iev) |
273 | { |
274 | fatal("should never need an fd for control messages"); |
275 | } |
276 | |
277 | int |
278 | control_close_any(struct control_sock *cs) |
279 | { |
280 | struct ctl_conn *c; |
281 | |
282 | c = TAILQ_FIRST(&ctl_conns)((&ctl_conns)->tqh_first); |
283 | if (c != NULL((void *)0)) { |
284 | log_warn("closing oldest control connection"); |
285 | control_close(c->iev.ibuf.fd, cs); |
286 | return (0); |
287 | } |
288 | log_warn("no control connections to close"); |
289 | return (-1); |
290 | } |