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