File: | src/usr.sbin/ldapd/control.c |
Warning: | line 238, 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.17 2021/04/20 21:11:56 dv 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 | /* ARGSUSED */ |
121 | void |
122 | control_accept(int listenfd, short event, void *arg) |
123 | { |
124 | struct control_sock *cs = arg; |
125 | int connfd; |
126 | socklen_t len; |
127 | struct sockaddr_un sun; |
128 | struct ctl_conn *c; |
129 | |
130 | event_add(&cs->cs_ev, NULL((void*)0)); |
131 | if ((event & EV_TIMEOUT0x01)) |
132 | return; |
133 | |
134 | len = sizeof(sun); |
135 | if ((connfd = accept_reserve(listenfd, |
136 | (struct sockaddr *)&sun, &len, FD_RESERVE8)) == -1) { |
137 | /* |
138 | * Pause accept if we are out of file descriptors, or |
139 | * libevent will haunt us here too. |
140 | */ |
141 | if (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24) { |
142 | struct timeval evtpause = { 1, 0 }; |
143 | |
144 | event_del(&cs->cs_ev); |
145 | evtimer_add(&cs->cs_evt, &evtpause)event_add(&cs->cs_evt, &evtpause); |
146 | } else if (errno(*__errno()) != EWOULDBLOCK35 && errno(*__errno()) != EINTR4) |
147 | log_warn("control_accept"); |
148 | return; |
149 | } |
150 | |
151 | if ((c = calloc(1, sizeof(*c))) == NULL((void*)0)) { |
152 | log_warn("control_accept"); |
153 | close(connfd); |
154 | return; |
155 | } |
156 | |
157 | log_debug("accepted control fd %d", connfd); |
158 | 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); |
159 | imsgev_init(&c->iev, connfd, cs, control_imsgev, control_needfd); |
160 | } |
161 | |
162 | struct ctl_conn * |
163 | control_connbyfd(int fd) |
164 | { |
165 | struct ctl_conn *c; |
166 | |
167 | TAILQ_FOREACH(c, &ctl_conns, entry)for((c) = ((&ctl_conns)->tqh_first); (c) != ((void*)0) ; (c) = ((c)->entry.tqe_next)) { |
168 | if (c->iev.ibuf.fd == fd) |
169 | break; |
170 | } |
171 | |
172 | return (c); |
173 | } |
174 | |
175 | void |
176 | control_close(int fd, struct control_sock *cs) |
177 | { |
178 | struct ctl_conn *c; |
179 | |
180 | if ((c = control_connbyfd(fd)) == NULL((void*)0)) { |
181 | log_warnx("control_close: fd %d: not found", fd); |
182 | return; |
183 | } |
184 | |
185 | log_debug("close control fd %d", c->iev.ibuf.fd); |
186 | 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); |
187 | imsgev_clear(&c->iev); |
188 | |
189 | /* Some file descriptors are available again. */ |
190 | if (evtimer_pending(&cs->cs_evt, NULL)event_pending(&cs->cs_evt, 0x01, ((void*)0))) { |
191 | evtimer_del(&cs->cs_evt)event_del(&cs->cs_evt); |
192 | event_add(&cs->cs_ev, NULL((void*)0)); |
193 | } |
194 | |
195 | free(c); |
196 | } |
197 | |
198 | static int |
199 | send_stats(struct imsgev *iev) |
200 | { |
201 | struct namespace *ns; |
202 | const struct btree_stat *st; |
203 | struct ns_stat nss; |
204 | |
205 | imsgev_compose(iev, IMSG_CTL_STATS, 0, iev->ibuf.pid, -1, |
206 | &stats, sizeof(stats)); |
207 | |
208 | TAILQ_FOREACH(ns, &conf->namespaces, next)for((ns) = ((&conf->namespaces)->tqh_first); (ns) != ((void*)0); (ns) = ((ns)->next.tqe_next)) { |
209 | if (namespace_has_referrals(ns)) |
210 | continue; |
211 | memset(&nss, 0, sizeof(nss)); |
212 | strlcpy(nss.suffix, ns->suffix, sizeof(nss.suffix)); |
213 | if ((st = btree_stat(ns->data_db)) != NULL((void*)0)) |
214 | bcopy(st, &nss.data_stat, sizeof(nss.data_stat)); |
215 | |
216 | if ((st = btree_stat(ns->indx_db)) != NULL((void*)0)) |
217 | bcopy(st, &nss.indx_stat, sizeof(nss.indx_stat)); |
218 | |
219 | imsgev_compose(iev, IMSG_CTL_NSSTATS, 0, iev->ibuf.pid, -1, |
220 | &nss, sizeof(nss)); |
221 | } |
222 | |
223 | imsgev_compose(iev, IMSG_CTL_END, 0, iev->ibuf.pid, -1, NULL((void*)0), 0); |
224 | |
225 | return 0; |
226 | } |
227 | |
228 | static void |
229 | control_imsgev(struct imsgev *iev, int code, struct imsg *imsg) |
230 | { |
231 | struct control_sock *cs; |
232 | struct ctl_conn *c; |
233 | int fd, verbose; |
234 | |
235 | cs = iev->data; |
236 | fd = iev->ibuf.fd; |
237 | |
238 | 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' | |
239 | log_warnx("%s: fd %d: not found", __func__, fd); |
240 | return; |
241 | } |
242 | |
243 | if (code != IMSGEV_IMSG0) { |
244 | control_close(fd, cs); |
245 | return; |
246 | } |
247 | |
248 | log_debug("%s: got imsg %d on fd %d", __func__, imsg->hdr.type, fd); |
249 | switch (imsg->hdr.type) { |
250 | case IMSG_CTL_STATS: |
251 | if (send_stats(iev) == -1) { |
252 | log_debug("%s: failed to send statistics", __func__); |
253 | control_close(fd, cs); |
254 | } |
255 | break; |
256 | case IMSG_CTL_LOG_VERBOSE: |
257 | if (imsg->hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof(verbose)) |
258 | break; |
259 | |
260 | bcopy(imsg->data, &verbose, sizeof(verbose)); |
261 | imsgev_compose(iev_ldapd, IMSG_CTL_LOG_VERBOSE, 0, 0, -1, |
262 | &verbose, sizeof(verbose)); |
263 | |
264 | log_setverbose(verbose); |
265 | break; |
266 | default: |
267 | log_warnx("%s: unexpected imsg %d", __func__, imsg->hdr.type); |
268 | break; |
269 | } |
270 | } |
271 | |
272 | void |
273 | control_needfd(struct imsgev *iev) |
274 | { |
275 | fatal("should never need an fd for control messages"); |
276 | } |
277 | |
278 | int |
279 | control_close_any(struct control_sock *cs) |
280 | { |
281 | struct ctl_conn *c; |
282 | |
283 | c = TAILQ_FIRST(&ctl_conns)((&ctl_conns)->tqh_first); |
284 | if (c != NULL((void*)0)) { |
285 | log_warn("closing oldest control connection"); |
286 | control_close(c->iev.ibuf.fd, cs); |
287 | return (0); |
288 | } |
289 | log_warn("no control connections to close"); |
290 | return (-1); |
291 | } |