1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <netinet/in.h>
30 #include <sys/socket.h>
35 #include "sd-daemon.h"
37 #include "alloc-util.h"
40 #include "parse-util.h"
41 #include "path-util.h"
42 #include "socket-util.h"
46 #define SNDBUF_SIZE (8*1024*1024)
48 static void unsetenv_all(bool unset_environment
) {
50 if (!unset_environment
)
53 unsetenv("LISTEN_PID");
54 unsetenv("LISTEN_FDS");
55 unsetenv("LISTEN_FDNAMES");
58 _public_
int sd_listen_fds(int unset_environment
) {
63 e
= getenv("LISTEN_PID");
69 r
= parse_pid(e
, &pid
);
74 if (getpid_cached() != pid
) {
79 e
= getenv("LISTEN_FDS");
89 assert_cc(SD_LISTEN_FDS_START
< INT_MAX
);
90 if (n
<= 0 || n
> INT_MAX
- SD_LISTEN_FDS_START
) {
95 for (fd
= SD_LISTEN_FDS_START
; fd
< SD_LISTEN_FDS_START
+ n
; fd
++) {
96 r
= fd_cloexec(fd
, true);
104 unsetenv_all(unset_environment
);
108 _public_
int sd_listen_fds_with_names(int unset_environment
, char ***names
) {
109 _cleanup_strv_free_
char **l
= NULL
;
111 int n_names
= 0, n_fds
;
116 return sd_listen_fds(unset_environment
);
118 e
= getenv("LISTEN_FDNAMES");
120 n_names
= strv_split_extract(&l
, e
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
122 unsetenv_all(unset_environment
);
130 n_fds
= sd_listen_fds(unset_environment
);
135 if (n_names
!= n_fds
)
138 r
= strv_extend_n(&l
, "unknown", n_fds
);
149 _public_
int sd_is_fifo(int fd
, const char *path
) {
152 assert_return(fd
>= 0, -EBADF
);
154 if (fstat(fd
, &st_fd
) < 0)
157 if (!S_ISFIFO(st_fd
.st_mode
))
163 if (stat(path
, &st_path
) < 0) {
165 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
172 st_path
.st_dev
== st_fd
.st_dev
&&
173 st_path
.st_ino
== st_fd
.st_ino
;
179 _public_
int sd_is_special(int fd
, const char *path
) {
182 assert_return(fd
>= 0, -EBADF
);
184 if (fstat(fd
, &st_fd
) < 0)
187 if (!S_ISREG(st_fd
.st_mode
) && !S_ISCHR(st_fd
.st_mode
))
193 if (stat(path
, &st_path
) < 0) {
195 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
201 if (S_ISREG(st_fd
.st_mode
) && S_ISREG(st_path
.st_mode
))
203 st_path
.st_dev
== st_fd
.st_dev
&&
204 st_path
.st_ino
== st_fd
.st_ino
;
205 else if (S_ISCHR(st_fd
.st_mode
) && S_ISCHR(st_path
.st_mode
))
206 return st_path
.st_rdev
== st_fd
.st_rdev
;
214 static int sd_is_socket_internal(int fd
, int type
, int listening
) {
217 assert_return(fd
>= 0, -EBADF
);
218 assert_return(type
>= 0, -EINVAL
);
220 if (fstat(fd
, &st_fd
) < 0)
223 if (!S_ISSOCK(st_fd
.st_mode
))
228 socklen_t l
= sizeof(other_type
);
230 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &other_type
, &l
) < 0)
233 if (l
!= sizeof(other_type
))
236 if (other_type
!= type
)
240 if (listening
>= 0) {
242 socklen_t l
= sizeof(accepting
);
244 if (getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &accepting
, &l
) < 0)
247 if (l
!= sizeof(accepting
))
250 if (!accepting
!= !listening
)
257 _public_
int sd_is_socket(int fd
, int family
, int type
, int listening
) {
260 assert_return(fd
>= 0, -EBADF
);
261 assert_return(family
>= 0, -EINVAL
);
263 r
= sd_is_socket_internal(fd
, type
, listening
);
268 union sockaddr_union sockaddr
= {};
269 socklen_t l
= sizeof(sockaddr
);
271 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
274 if (l
< sizeof(sa_family_t
))
277 return sockaddr
.sa
.sa_family
== family
;
283 _public_
int sd_is_socket_inet(int fd
, int family
, int type
, int listening
, uint16_t port
) {
284 union sockaddr_union sockaddr
= {};
285 socklen_t l
= sizeof(sockaddr
);
288 assert_return(fd
>= 0, -EBADF
);
289 assert_return(IN_SET(family
, 0, AF_INET
, AF_INET6
), -EINVAL
);
291 r
= sd_is_socket_internal(fd
, type
, listening
);
295 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
298 if (l
< sizeof(sa_family_t
))
301 if (!IN_SET(sockaddr
.sa
.sa_family
, AF_INET
, AF_INET6
))
305 if (sockaddr
.sa
.sa_family
!= family
)
309 if (sockaddr
.sa
.sa_family
== AF_INET
) {
310 if (l
< sizeof(struct sockaddr_in
))
313 return htobe16(port
) == sockaddr
.in
.sin_port
;
315 if (l
< sizeof(struct sockaddr_in6
))
318 return htobe16(port
) == sockaddr
.in6
.sin6_port
;
325 _public_
int sd_is_socket_sockaddr(int fd
, int type
, const struct sockaddr
* addr
, unsigned addr_len
, int listening
) {
326 union sockaddr_union sockaddr
= {};
327 socklen_t l
= sizeof(sockaddr
);
330 assert_return(fd
>= 0, -EBADF
);
331 assert_return(addr
, -EINVAL
);
332 assert_return(addr_len
>= sizeof(sa_family_t
), -ENOBUFS
);
333 assert_return(IN_SET(addr
->sa_family
, AF_INET
, AF_INET6
), -EPFNOSUPPORT
);
335 r
= sd_is_socket_internal(fd
, type
, listening
);
339 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
342 if (l
< sizeof(sa_family_t
))
345 if (sockaddr
.sa
.sa_family
!= addr
->sa_family
)
348 if (sockaddr
.sa
.sa_family
== AF_INET
) {
349 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) addr
;
351 if (l
< sizeof(struct sockaddr_in
) || addr_len
< sizeof(struct sockaddr_in
))
354 if (in
->sin_port
!= 0 &&
355 sockaddr
.in
.sin_port
!= in
->sin_port
)
358 return sockaddr
.in
.sin_addr
.s_addr
== in
->sin_addr
.s_addr
;
361 const struct sockaddr_in6
*in
= (const struct sockaddr_in6
*) addr
;
363 if (l
< sizeof(struct sockaddr_in6
) || addr_len
< sizeof(struct sockaddr_in6
))
366 if (in
->sin6_port
!= 0 &&
367 sockaddr
.in6
.sin6_port
!= in
->sin6_port
)
370 if (in
->sin6_flowinfo
!= 0 &&
371 sockaddr
.in6
.sin6_flowinfo
!= in
->sin6_flowinfo
)
374 if (in
->sin6_scope_id
!= 0 &&
375 sockaddr
.in6
.sin6_scope_id
!= in
->sin6_scope_id
)
378 return memcmp(sockaddr
.in6
.sin6_addr
.s6_addr
, in
->sin6_addr
.s6_addr
,
379 sizeof(in
->sin6_addr
.s6_addr
)) == 0;
383 _public_
int sd_is_socket_unix(int fd
, int type
, int listening
, const char *path
, size_t length
) {
384 union sockaddr_union sockaddr
= {};
385 socklen_t l
= sizeof(sockaddr
);
388 assert_return(fd
>= 0, -EBADF
);
390 r
= sd_is_socket_internal(fd
, type
, listening
);
394 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
397 if (l
< sizeof(sa_family_t
))
400 if (sockaddr
.sa
.sa_family
!= AF_UNIX
)
405 length
= strlen(path
);
409 return l
== offsetof(struct sockaddr_un
, sun_path
);
412 /* Normal path socket */
414 (l
>= offsetof(struct sockaddr_un
, sun_path
) + length
+ 1) &&
415 memcmp(path
, sockaddr
.un
.sun_path
, length
+1) == 0;
417 /* Abstract namespace socket */
419 (l
== offsetof(struct sockaddr_un
, sun_path
) + length
) &&
420 memcmp(path
, sockaddr
.un
.sun_path
, length
) == 0;
426 _public_
int sd_is_mq(int fd
, const char *path
) {
429 /* Check that the fd is valid */
430 assert_return(fcntl(fd
, F_GETFD
) >= 0, -errno
);
432 if (mq_getattr(fd
, &attr
) < 0) {
434 /* A non-mq fd (or an invalid one, but we ruled that out above) */
440 char fpath
[PATH_MAX
];
443 assert_return(path_is_absolute(path
), -EINVAL
);
445 if (fstat(fd
, &a
) < 0)
448 strncpy(stpcpy(fpath
, "/dev/mqueue"), path
, sizeof(fpath
) - 12);
449 fpath
[sizeof(fpath
)-1] = 0;
451 if (stat(fpath
, &b
) < 0)
454 if (a
.st_dev
!= b
.st_dev
||
455 a
.st_ino
!= b
.st_ino
)
462 _public_
int sd_pid_notify_with_fds(pid_t pid
, int unset_environment
, const char *state
, const int *fds
, unsigned n_fds
) {
463 union sockaddr_union sockaddr
= {
464 .sa
.sa_family
= AF_UNIX
,
466 struct iovec iovec
= {
467 .iov_base
= (char*) state
,
469 struct msghdr msghdr
= {
472 .msg_name
= &sockaddr
,
474 _cleanup_close_
int fd
= -1;
475 struct cmsghdr
*cmsg
= NULL
;
485 if (n_fds
> 0 && !fds
) {
490 e
= getenv("NOTIFY_SOCKET");
494 /* Must be an abstract socket, or an absolute path */
495 if (!IN_SET(e
[0], '@', '/') || e
[1] == 0) {
500 if (strlen(e
) > sizeof(sockaddr
.un
.sun_path
)) {
505 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
511 fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
513 iovec
.iov_len
= strlen(state
);
515 strncpy(sockaddr
.un
.sun_path
, e
, sizeof(sockaddr
.un
.sun_path
));
516 if (sockaddr
.un
.sun_path
[0] == '@')
517 sockaddr
.un
.sun_path
[0] = 0;
519 msghdr
.msg_namelen
= SOCKADDR_UN_LEN(sockaddr
.un
);
521 have_pid
= pid
!= 0 && pid
!= getpid_cached();
523 if (n_fds
> 0 || have_pid
) {
524 /* CMSG_SPACE(0) may return value different than zero, which results in miscalculated controllen. */
525 msghdr
.msg_controllen
=
526 (n_fds
> 0 ? CMSG_SPACE(sizeof(int) * n_fds
) : 0) +
527 (have_pid
? CMSG_SPACE(sizeof(struct ucred
)) : 0);
529 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
531 cmsg
= CMSG_FIRSTHDR(&msghdr
);
533 cmsg
->cmsg_level
= SOL_SOCKET
;
534 cmsg
->cmsg_type
= SCM_RIGHTS
;
535 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * n_fds
);
537 memcpy(CMSG_DATA(cmsg
), fds
, sizeof(int) * n_fds
);
540 assert_se(cmsg
= CMSG_NXTHDR(&msghdr
, cmsg
));
546 cmsg
->cmsg_level
= SOL_SOCKET
;
547 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
548 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct ucred
));
550 ucred
= (struct ucred
*) CMSG_DATA(cmsg
);
552 ucred
->uid
= getuid();
553 ucred
->gid
= getgid();
557 /* First try with fake ucred data, as requested */
558 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) >= 0) {
563 /* If that failed, try with our own ucred instead */
565 msghdr
.msg_controllen
-= CMSG_SPACE(sizeof(struct ucred
));
566 if (msghdr
.msg_controllen
== 0)
567 msghdr
.msg_control
= NULL
;
569 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) >= 0) {
578 if (unset_environment
)
579 unsetenv("NOTIFY_SOCKET");
584 _public_
int sd_pid_notify(pid_t pid
, int unset_environment
, const char *state
) {
585 return sd_pid_notify_with_fds(pid
, unset_environment
, state
, NULL
, 0);
588 _public_
int sd_notify(int unset_environment
, const char *state
) {
589 return sd_pid_notify_with_fds(0, unset_environment
, state
, NULL
, 0);
592 _public_
int sd_pid_notifyf(pid_t pid
, int unset_environment
, const char *format
, ...) {
593 _cleanup_free_
char *p
= NULL
;
599 va_start(ap
, format
);
600 r
= vasprintf(&p
, format
, ap
);
607 return sd_pid_notify(pid
, unset_environment
, p
);
610 _public_
int sd_notifyf(int unset_environment
, const char *format
, ...) {
611 _cleanup_free_
char *p
= NULL
;
617 va_start(ap
, format
);
618 r
= vasprintf(&p
, format
, ap
);
625 return sd_pid_notify(0, unset_environment
, p
);
628 _public_
int sd_booted(void) {
629 /* We test whether the runtime unit file directory has been
630 * created. This takes place in mount-setup.c, so is
631 * guaranteed to happen very early during boot. */
633 return laccess("/run/systemd/system/", F_OK
) >= 0;
636 _public_
int sd_watchdog_enabled(int unset_environment
, uint64_t *usec
) {
637 const char *s
, *p
= ""; /* p is set to dummy value to do unsetting */
641 s
= getenv("WATCHDOG_USEC");
645 r
= safe_atou64(s
, &u
);
648 if (u
<= 0 || u
>= USEC_INFINITY
) {
653 p
= getenv("WATCHDOG_PID");
657 r
= parse_pid(p
, &pid
);
661 /* Is this for us? */
662 if (getpid_cached() != pid
) {
674 if (unset_environment
&& s
)
675 unsetenv("WATCHDOG_USEC");
676 if (unset_environment
&& p
)
677 unsetenv("WATCHDOG_PID");