chiark / gitweb /
remove unused includes
[elogind.git] / src / libsystemd / sd-daemon / sd-daemon.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
25 #include <netinet/in.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <stddef.h>
33 #include <limits.h>
34 #include <mqueue.h>
35
36 #include "util.h"
37 #include "path-util.h"
38 #include "socket-util.h"
39 #include "sd-daemon.h"
40
41 _public_ int sd_listen_fds(int unset_environment) {
42         const char *e;
43         unsigned n;
44         int r, fd;
45         pid_t pid;
46
47         e = getenv("LISTEN_PID");
48         if (!e) {
49                 r = 0;
50                 goto finish;
51         }
52
53         r = parse_pid(e, &pid);
54         if (r < 0)
55                 goto finish;
56
57         /* Is this for us? */
58         if (getpid() != pid) {
59                 r = 0;
60                 goto finish;
61         }
62
63         e = getenv("LISTEN_FDS");
64         if (!e) {
65                 r = 0;
66                 goto finish;
67         }
68
69         r = safe_atou(e, &n);
70         if (r < 0)
71                 goto finish;
72
73         for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) n; fd ++) {
74                 r = fd_cloexec(fd, true);
75                 if (r < 0)
76                         goto finish;
77         }
78
79         r = (int) n;
80
81 finish:
82         if (unset_environment) {
83                 unsetenv("LISTEN_PID");
84                 unsetenv("LISTEN_FDS");
85         }
86
87         return r;
88 }
89
90 _public_ int sd_is_fifo(int fd, const char *path) {
91         struct stat st_fd;
92
93         assert_return(fd >= 0, -EINVAL);
94
95         if (fstat(fd, &st_fd) < 0)
96                 return -errno;
97
98         if (!S_ISFIFO(st_fd.st_mode))
99                 return 0;
100
101         if (path) {
102                 struct stat st_path;
103
104                 if (stat(path, &st_path) < 0) {
105
106                         if (errno == ENOENT || errno == ENOTDIR)
107                                 return 0;
108
109                         return -errno;
110                 }
111
112                 return
113                         st_path.st_dev == st_fd.st_dev &&
114                         st_path.st_ino == st_fd.st_ino;
115         }
116
117         return 1;
118 }
119
120 _public_ int sd_is_special(int fd, const char *path) {
121         struct stat st_fd;
122
123         assert_return(fd >= 0, -EINVAL);
124
125         if (fstat(fd, &st_fd) < 0)
126                 return -errno;
127
128         if (!S_ISREG(st_fd.st_mode) && !S_ISCHR(st_fd.st_mode))
129                 return 0;
130
131         if (path) {
132                 struct stat st_path;
133
134                 if (stat(path, &st_path) < 0) {
135
136                         if (errno == ENOENT || errno == ENOTDIR)
137                                 return 0;
138
139                         return -errno;
140                 }
141
142                 if (S_ISREG(st_fd.st_mode) && S_ISREG(st_path.st_mode))
143                         return
144                                 st_path.st_dev == st_fd.st_dev &&
145                                 st_path.st_ino == st_fd.st_ino;
146                 else if (S_ISCHR(st_fd.st_mode) && S_ISCHR(st_path.st_mode))
147                         return st_path.st_rdev == st_fd.st_rdev;
148                 else
149                         return 0;
150         }
151
152         return 1;
153 }
154
155 static int sd_is_socket_internal(int fd, int type, int listening) {
156         struct stat st_fd;
157
158         assert_return(fd >= 0, -EINVAL);
159         assert_return(type >= 0, -EINVAL);
160
161         if (fstat(fd, &st_fd) < 0)
162                 return -errno;
163
164         if (!S_ISSOCK(st_fd.st_mode))
165                 return 0;
166
167         if (type != 0) {
168                 int other_type = 0;
169                 socklen_t l = sizeof(other_type);
170
171                 if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
172                         return -errno;
173
174                 if (l != sizeof(other_type))
175                         return -EINVAL;
176
177                 if (other_type != type)
178                         return 0;
179         }
180
181         if (listening >= 0) {
182                 int accepting = 0;
183                 socklen_t l = sizeof(accepting);
184
185                 if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
186                         return -errno;
187
188                 if (l != sizeof(accepting))
189                         return -EINVAL;
190
191                 if (!accepting != !listening)
192                         return 0;
193         }
194
195         return 1;
196 }
197
198 _public_ int sd_is_socket(int fd, int family, int type, int listening) {
199         int r;
200
201         assert_return(fd >= 0, -EINVAL);
202         assert_return(family >= 0, -EINVAL);
203
204         r = sd_is_socket_internal(fd, type, listening);
205         if (r <= 0)
206                 return r;
207
208         if (family > 0) {
209                 union sockaddr_union sockaddr = {};
210                 socklen_t l = sizeof(sockaddr);
211
212                 if (getsockname(fd, &sockaddr.sa, &l) < 0)
213                         return -errno;
214
215                 if (l < sizeof(sa_family_t))
216                         return -EINVAL;
217
218                 return sockaddr.sa.sa_family == family;
219         }
220
221         return 1;
222 }
223
224 _public_ int sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
225         union sockaddr_union sockaddr = {};
226         socklen_t l = sizeof(sockaddr);
227         int r;
228
229         assert_return(fd >= 0, -EINVAL);
230         assert_return(IN_SET(family, 0, AF_INET, AF_INET6), -EINVAL);
231
232         r = sd_is_socket_internal(fd, type, listening);
233         if (r <= 0)
234                 return r;
235
236         if (getsockname(fd, &sockaddr.sa, &l) < 0)
237                 return -errno;
238
239         if (l < sizeof(sa_family_t))
240                 return -EINVAL;
241
242         if (sockaddr.sa.sa_family != AF_INET &&
243             sockaddr.sa.sa_family != AF_INET6)
244                 return 0;
245
246         if (family != 0)
247                 if (sockaddr.sa.sa_family != family)
248                         return 0;
249
250         if (port > 0) {
251                 if (sockaddr.sa.sa_family == AF_INET) {
252                         if (l < sizeof(struct sockaddr_in))
253                                 return -EINVAL;
254
255                         return htons(port) == sockaddr.in.sin_port;
256                 } else {
257                         if (l < sizeof(struct sockaddr_in6))
258                                 return -EINVAL;
259
260                         return htons(port) == sockaddr.in6.sin6_port;
261                 }
262         }
263
264         return 1;
265 }
266
267 _public_ int sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
268         union sockaddr_union sockaddr = {};
269         socklen_t l = sizeof(sockaddr);
270         int r;
271
272         assert_return(fd >= 0, -EINVAL);
273
274         r = sd_is_socket_internal(fd, type, listening);
275         if (r <= 0)
276                 return r;
277
278         if (getsockname(fd, &sockaddr.sa, &l) < 0)
279                 return -errno;
280
281         if (l < sizeof(sa_family_t))
282                 return -EINVAL;
283
284         if (sockaddr.sa.sa_family != AF_UNIX)
285                 return 0;
286
287         if (path) {
288                 if (length == 0)
289                         length = strlen(path);
290
291                 if (length == 0)
292                         /* Unnamed socket */
293                         return l == offsetof(struct sockaddr_un, sun_path);
294
295                 if (path[0])
296                         /* Normal path socket */
297                         return
298                                 (l >= offsetof(struct sockaddr_un, sun_path) + length + 1) &&
299                                 memcmp(path, sockaddr.un.sun_path, length+1) == 0;
300                 else
301                         /* Abstract namespace socket */
302                         return
303                                 (l == offsetof(struct sockaddr_un, sun_path) + length) &&
304                                 memcmp(path, sockaddr.un.sun_path, length) == 0;
305         }
306
307         return 1;
308 }
309
310 _public_ int sd_is_mq(int fd, const char *path) {
311         struct mq_attr attr;
312
313         assert_return(fd >= 0, -EINVAL);
314
315         if (mq_getattr(fd, &attr) < 0)
316                 return -errno;
317
318         if (path) {
319                 char fpath[PATH_MAX];
320                 struct stat a, b;
321
322                 assert_return(path_is_absolute(path), -EINVAL);
323
324                 if (fstat(fd, &a) < 0)
325                         return -errno;
326
327                 strncpy(stpcpy(fpath, "/dev/mqueue"), path, sizeof(fpath) - 12);
328                 fpath[sizeof(fpath)-1] = 0;
329
330                 if (stat(fpath, &b) < 0)
331                         return -errno;
332
333                 if (a.st_dev != b.st_dev ||
334                     a.st_ino != b.st_ino)
335                         return 0;
336         }
337
338         return 1;
339 }
340
341 _public_ int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds) {
342         union sockaddr_union sockaddr = {
343                 .sa.sa_family = AF_UNIX,
344         };
345         struct iovec iovec = {
346                 .iov_base = (char*) state,
347         };
348         struct msghdr msghdr = {
349                 .msg_iov = &iovec,
350                 .msg_iovlen = 1,
351                 .msg_name = &sockaddr,
352         };
353         union {
354                 struct cmsghdr cmsghdr;
355                 uint8_t buf[CMSG_SPACE(sizeof(struct ucred)) +
356                             CMSG_SPACE(sizeof(int) * n_fds)];
357         } control;
358         _cleanup_close_ int fd = -1;
359         struct cmsghdr *cmsg = NULL;
360         const char *e;
361         size_t controllen_without_ucred = 0;
362         bool try_without_ucred = false;
363         int r;
364
365         if (!state) {
366                 r = -EINVAL;
367                 goto finish;
368         }
369
370         if (n_fds > 0 && !fds) {
371                 r = -EINVAL;
372                 goto finish;
373         }
374
375         e = getenv("NOTIFY_SOCKET");
376         if (!e)
377                 return 0;
378
379         /* Must be an abstract socket, or an absolute path */
380         if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
381                 r = -EINVAL;
382                 goto finish;
383         }
384
385         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
386         if (fd < 0) {
387                 r = -errno;
388                 goto finish;
389         }
390
391         iovec.iov_len = strlen(state);
392
393         strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
394         if (sockaddr.un.sun_path[0] == '@')
395                 sockaddr.un.sun_path[0] = 0;
396
397         msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e);
398         if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
399                 msghdr.msg_namelen = sizeof(struct sockaddr_un);
400
401         if (n_fds > 0) {
402                 msghdr.msg_control = &control;
403                 msghdr.msg_controllen = CMSG_LEN(sizeof(int) * n_fds);
404
405                 cmsg = CMSG_FIRSTHDR(&msghdr);
406                 cmsg->cmsg_level = SOL_SOCKET;
407                 cmsg->cmsg_type = SCM_RIGHTS;
408                 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
409
410                 memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * n_fds);
411         }
412
413         if (pid != 0 && pid != getpid()) {
414                 struct ucred *ucred;
415
416                 try_without_ucred = true;
417                 controllen_without_ucred = msghdr.msg_controllen;
418
419                 msghdr.msg_control = &control;
420                 msghdr.msg_controllen += CMSG_LEN(sizeof(struct ucred));
421
422                 if (cmsg)
423                         cmsg = CMSG_NXTHDR(&msghdr, cmsg);
424                 else
425                         cmsg = CMSG_FIRSTHDR(&msghdr);
426
427                 cmsg->cmsg_level = SOL_SOCKET;
428                 cmsg->cmsg_type = SCM_CREDENTIALS;
429                 cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
430
431                 ucred = (struct ucred*) CMSG_DATA(cmsg);
432                 ucred->pid = pid;
433                 ucred->uid = getuid();
434                 ucred->gid = getgid();
435         }
436
437         /* First try with fake ucred data, as requested */
438         if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
439                 r = 1;
440                 goto finish;
441         }
442
443         /* If that failed, try with our own ucred instead */
444         if (try_without_ucred) {
445                 if (controllen_without_ucred <= 0)
446                         msghdr.msg_control = NULL;
447                 msghdr.msg_controllen = controllen_without_ucred;
448
449                 if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
450                         r = 1;
451                         goto finish;
452                 }
453         }
454
455         r = -errno;
456
457 finish:
458         if (unset_environment)
459                 unsetenv("NOTIFY_SOCKET");
460
461         return r;
462 }
463
464 _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) {
465         return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0);
466 }
467
468 _public_ int sd_notify(int unset_environment, const char *state) {
469         return sd_pid_notify_with_fds(0, unset_environment, state, NULL, 0);
470 }
471
472 _public_ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) {
473         _cleanup_free_ char *p = NULL;
474         int r;
475
476         if (format) {
477                 va_list ap;
478
479                 va_start(ap, format);
480                 r = vasprintf(&p, format, ap);
481                 va_end(ap);
482
483                 if (r < 0 || !p)
484                         return -ENOMEM;
485         }
486
487         return sd_pid_notify(pid, unset_environment, p);
488 }
489
490 _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
491         _cleanup_free_ char *p = NULL;
492         int r;
493
494         if (format) {
495                 va_list ap;
496
497                 va_start(ap, format);
498                 r = vasprintf(&p, format, ap);
499                 va_end(ap);
500
501                 if (r < 0 || !p)
502                         return -ENOMEM;
503         }
504
505         return sd_pid_notify(0, unset_environment, p);
506 }
507
508 _public_ int sd_booted(void) {
509         struct stat st;
510
511         /* We test whether the runtime unit file directory has been
512          * created. This takes place in mount-setup.c, so is
513          * guaranteed to happen very early during boot. */
514
515         if (lstat("/run/systemd/system/", &st) < 0)
516                 return 0;
517
518         return !!S_ISDIR(st.st_mode);
519 }
520
521 _public_ int sd_watchdog_enabled(int unset_environment, uint64_t *usec) {
522         const char *s, *p = ""; /* p is set to dummy value to do unsetting */
523         uint64_t u;
524         int r = 0;
525
526         s = getenv("WATCHDOG_USEC");
527         if (!s)
528                 goto finish;
529
530         r = safe_atou64(s, &u);
531         if (r < 0)
532                 goto finish;
533         if (u <= 0) {
534                 r = -EINVAL;
535                 goto finish;
536         }
537
538         p = getenv("WATCHDOG_PID");
539         if (p) {
540                 pid_t pid;
541
542                 r = parse_pid(p, &pid);
543                 if (r < 0)
544                         goto finish;
545
546                 /* Is this for us? */
547                 if (getpid() != pid) {
548                         r = 0;
549                         goto finish;
550                 }
551         }
552
553         if (usec)
554                 *usec = u;
555
556         r = 1;
557
558 finish:
559         if (unset_environment && s)
560                 unsetenv("WATCHDOG_USEC");
561         if (unset_environment && p)
562                 unsetenv("WATCHDOG_PID");
563
564         return r;
565 }