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 "process-util.h"
43 #include "socket-util.h"
47 #define SNDBUF_SIZE (8*1024*1024)
49 static void unsetenv_all(bool unset_environment
) {
51 if (!unset_environment
)
54 unsetenv("LISTEN_PID");
55 unsetenv("LISTEN_FDS");
56 unsetenv("LISTEN_FDNAMES");
59 _public_
int sd_listen_fds(int unset_environment
) {
64 e
= getenv("LISTEN_PID");
70 r
= parse_pid(e
, &pid
);
75 if (getpid_cached() != pid
) {
80 e
= getenv("LISTEN_FDS");
90 assert_cc(SD_LISTEN_FDS_START
< INT_MAX
);
91 if (n
<= 0 || n
> INT_MAX
- SD_LISTEN_FDS_START
) {
96 for (fd
= SD_LISTEN_FDS_START
; fd
< SD_LISTEN_FDS_START
+ n
; fd
++) {
97 r
= fd_cloexec(fd
, true);
105 unsetenv_all(unset_environment
);
109 _public_
int sd_listen_fds_with_names(int unset_environment
, char ***names
) {
110 _cleanup_strv_free_
char **l
= NULL
;
112 int n_names
= 0, n_fds
;
117 return sd_listen_fds(unset_environment
);
119 e
= getenv("LISTEN_FDNAMES");
121 n_names
= strv_split_extract(&l
, e
, ":", EXTRACT_DONT_COALESCE_SEPARATORS
);
123 unsetenv_all(unset_environment
);
131 n_fds
= sd_listen_fds(unset_environment
);
136 if (n_names
!= n_fds
)
139 r
= strv_extend_n(&l
, "unknown", n_fds
);
150 _public_
int sd_is_fifo(int fd
, const char *path
) {
153 assert_return(fd
>= 0, -EBADF
);
155 if (fstat(fd
, &st_fd
) < 0)
158 if (!S_ISFIFO(st_fd
.st_mode
))
164 if (stat(path
, &st_path
) < 0) {
166 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
173 st_path
.st_dev
== st_fd
.st_dev
&&
174 st_path
.st_ino
== st_fd
.st_ino
;
180 _public_
int sd_is_special(int fd
, const char *path
) {
183 assert_return(fd
>= 0, -EBADF
);
185 if (fstat(fd
, &st_fd
) < 0)
188 if (!S_ISREG(st_fd
.st_mode
) && !S_ISCHR(st_fd
.st_mode
))
194 if (stat(path
, &st_path
) < 0) {
196 if (IN_SET(errno
, ENOENT
, ENOTDIR
))
202 if (S_ISREG(st_fd
.st_mode
) && S_ISREG(st_path
.st_mode
))
204 st_path
.st_dev
== st_fd
.st_dev
&&
205 st_path
.st_ino
== st_fd
.st_ino
;
206 else if (S_ISCHR(st_fd
.st_mode
) && S_ISCHR(st_path
.st_mode
))
207 return st_path
.st_rdev
== st_fd
.st_rdev
;
215 static int sd_is_socket_internal(int fd
, int type
, int listening
) {
218 assert_return(fd
>= 0, -EBADF
);
219 assert_return(type
>= 0, -EINVAL
);
221 if (fstat(fd
, &st_fd
) < 0)
224 if (!S_ISSOCK(st_fd
.st_mode
))
229 socklen_t l
= sizeof(other_type
);
231 if (getsockopt(fd
, SOL_SOCKET
, SO_TYPE
, &other_type
, &l
) < 0)
234 if (l
!= sizeof(other_type
))
237 if (other_type
!= type
)
241 if (listening
>= 0) {
243 socklen_t l
= sizeof(accepting
);
245 if (getsockopt(fd
, SOL_SOCKET
, SO_ACCEPTCONN
, &accepting
, &l
) < 0)
248 if (l
!= sizeof(accepting
))
251 if (!accepting
!= !listening
)
258 _public_
int sd_is_socket(int fd
, int family
, int type
, int listening
) {
261 assert_return(fd
>= 0, -EBADF
);
262 assert_return(family
>= 0, -EINVAL
);
264 r
= sd_is_socket_internal(fd
, type
, listening
);
269 union sockaddr_union sockaddr
= {};
270 socklen_t l
= sizeof(sockaddr
);
272 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
275 if (l
< sizeof(sa_family_t
))
278 return sockaddr
.sa
.sa_family
== family
;
284 _public_
int sd_is_socket_inet(int fd
, int family
, int type
, int listening
, uint16_t port
) {
285 union sockaddr_union sockaddr
= {};
286 socklen_t l
= sizeof(sockaddr
);
289 assert_return(fd
>= 0, -EBADF
);
290 assert_return(IN_SET(family
, 0, AF_INET
, AF_INET6
), -EINVAL
);
292 r
= sd_is_socket_internal(fd
, type
, listening
);
296 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
299 if (l
< sizeof(sa_family_t
))
302 if (!IN_SET(sockaddr
.sa
.sa_family
, AF_INET
, AF_INET6
))
306 if (sockaddr
.sa
.sa_family
!= family
)
312 r
= sockaddr_port(&sockaddr
.sa
, &sa_port
);
316 return port
== sa_port
;
322 _public_
int sd_is_socket_sockaddr(int fd
, int type
, const struct sockaddr
* addr
, unsigned addr_len
, int listening
) {
323 union sockaddr_union sockaddr
= {};
324 socklen_t l
= sizeof(sockaddr
);
327 assert_return(fd
>= 0, -EBADF
);
328 assert_return(addr
, -EINVAL
);
329 assert_return(addr_len
>= sizeof(sa_family_t
), -ENOBUFS
);
330 assert_return(IN_SET(addr
->sa_family
, AF_INET
, AF_INET6
), -EPFNOSUPPORT
);
332 r
= sd_is_socket_internal(fd
, type
, listening
);
336 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
339 if (l
< sizeof(sa_family_t
))
342 if (sockaddr
.sa
.sa_family
!= addr
->sa_family
)
345 if (sockaddr
.sa
.sa_family
== AF_INET
) {
346 const struct sockaddr_in
*in
= (const struct sockaddr_in
*) addr
;
348 if (l
< sizeof(struct sockaddr_in
) || addr_len
< sizeof(struct sockaddr_in
))
351 if (in
->sin_port
!= 0 &&
352 sockaddr
.in
.sin_port
!= in
->sin_port
)
355 return sockaddr
.in
.sin_addr
.s_addr
== in
->sin_addr
.s_addr
;
358 const struct sockaddr_in6
*in
= (const struct sockaddr_in6
*) addr
;
360 if (l
< sizeof(struct sockaddr_in6
) || addr_len
< sizeof(struct sockaddr_in6
))
363 if (in
->sin6_port
!= 0 &&
364 sockaddr
.in6
.sin6_port
!= in
->sin6_port
)
367 if (in
->sin6_flowinfo
!= 0 &&
368 sockaddr
.in6
.sin6_flowinfo
!= in
->sin6_flowinfo
)
371 if (in
->sin6_scope_id
!= 0 &&
372 sockaddr
.in6
.sin6_scope_id
!= in
->sin6_scope_id
)
375 return memcmp(sockaddr
.in6
.sin6_addr
.s6_addr
, in
->sin6_addr
.s6_addr
,
376 sizeof(in
->sin6_addr
.s6_addr
)) == 0;
380 _public_
int sd_is_socket_unix(int fd
, int type
, int listening
, const char *path
, size_t length
) {
381 union sockaddr_union sockaddr
= {};
382 socklen_t l
= sizeof(sockaddr
);
385 assert_return(fd
>= 0, -EBADF
);
387 r
= sd_is_socket_internal(fd
, type
, listening
);
391 if (getsockname(fd
, &sockaddr
.sa
, &l
) < 0)
394 if (l
< sizeof(sa_family_t
))
397 if (sockaddr
.sa
.sa_family
!= AF_UNIX
)
402 length
= strlen(path
);
406 return l
== offsetof(struct sockaddr_un
, sun_path
);
409 /* Normal path socket */
411 (l
>= offsetof(struct sockaddr_un
, sun_path
) + length
+ 1) &&
412 memcmp(path
, sockaddr
.un
.sun_path
, length
+1) == 0;
414 /* Abstract namespace socket */
416 (l
== offsetof(struct sockaddr_un
, sun_path
) + length
) &&
417 memcmp(path
, sockaddr
.un
.sun_path
, length
) == 0;
423 _public_
int sd_is_mq(int fd
, const char *path
) {
426 /* Check that the fd is valid */
427 assert_return(fcntl(fd
, F_GETFD
) >= 0, -errno
);
429 if (mq_getattr(fd
, &attr
) < 0) {
431 /* A non-mq fd (or an invalid one, but we ruled that out above) */
437 char fpath
[PATH_MAX
];
440 assert_return(path_is_absolute(path
), -EINVAL
);
442 if (fstat(fd
, &a
) < 0)
445 strncpy(stpcpy(fpath
, "/dev/mqueue"), path
, sizeof(fpath
) - 12);
446 fpath
[sizeof(fpath
)-1] = 0;
448 if (stat(fpath
, &b
) < 0)
451 if (a
.st_dev
!= b
.st_dev
||
452 a
.st_ino
!= b
.st_ino
)
459 _public_
int sd_pid_notify_with_fds(
461 int unset_environment
,
466 union sockaddr_union sockaddr
= {
467 .sa
.sa_family
= AF_UNIX
,
469 struct iovec iovec
= {
470 .iov_base
= (char*) state
,
472 struct msghdr msghdr
= {
475 .msg_name
= &sockaddr
,
477 _cleanup_close_
int fd
= -1;
478 struct cmsghdr
*cmsg
= NULL
;
488 if (n_fds
> 0 && !fds
) {
493 e
= getenv("NOTIFY_SOCKET");
497 /* Must be an abstract socket, or an absolute path */
498 if (!IN_SET(e
[0], '@', '/') || e
[1] == 0) {
503 if (strlen(e
) > sizeof(sockaddr
.un
.sun_path
)) {
508 fd
= socket(AF_UNIX
, SOCK_DGRAM
|SOCK_CLOEXEC
, 0);
514 (void) fd_inc_sndbuf(fd
, SNDBUF_SIZE
);
516 iovec
.iov_len
= strlen(state
);
518 strncpy(sockaddr
.un
.sun_path
, e
, sizeof(sockaddr
.un
.sun_path
));
519 if (sockaddr
.un
.sun_path
[0] == '@')
520 sockaddr
.un
.sun_path
[0] = 0;
522 msghdr
.msg_namelen
= SOCKADDR_UN_LEN(sockaddr
.un
);
525 (pid
!= 0 && pid
!= getpid_cached()) ||
526 getuid() != geteuid() ||
527 getgid() != getegid();
529 if (n_fds
> 0 || send_ucred
) {
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 (send_ucred
? CMSG_SPACE(sizeof(struct ucred
)) : 0);
535 msghdr
.msg_control
= alloca0(msghdr
.msg_controllen
);
537 cmsg
= CMSG_FIRSTHDR(&msghdr
);
539 cmsg
->cmsg_level
= SOL_SOCKET
;
540 cmsg
->cmsg_type
= SCM_RIGHTS
;
541 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * n_fds
);
543 memcpy(CMSG_DATA(cmsg
), fds
, sizeof(int) * n_fds
);
546 assert_se(cmsg
= CMSG_NXTHDR(&msghdr
, cmsg
));
552 cmsg
->cmsg_level
= SOL_SOCKET
;
553 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
554 cmsg
->cmsg_len
= CMSG_LEN(sizeof(struct ucred
));
556 ucred
= (struct ucred
*) CMSG_DATA(cmsg
);
557 ucred
->pid
= pid
!= 0 ? pid
: getpid_cached();
558 ucred
->uid
= getuid();
559 ucred
->gid
= getgid();
563 /* First try with fake ucred data, as requested */
564 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) >= 0) {
569 /* If that failed, try with our own ucred instead */
571 msghdr
.msg_controllen
-= CMSG_SPACE(sizeof(struct ucred
));
572 if (msghdr
.msg_controllen
== 0)
573 msghdr
.msg_control
= NULL
;
575 if (sendmsg(fd
, &msghdr
, MSG_NOSIGNAL
) >= 0) {
584 if (unset_environment
)
585 unsetenv("NOTIFY_SOCKET");
590 _public_
int sd_pid_notify(pid_t pid
, int unset_environment
, const char *state
) {
591 return sd_pid_notify_with_fds(pid
, unset_environment
, state
, NULL
, 0);
594 _public_
int sd_notify(int unset_environment
, const char *state
) {
595 return sd_pid_notify_with_fds(0, unset_environment
, state
, NULL
, 0);
598 _public_
int sd_pid_notifyf(pid_t pid
, int unset_environment
, const char *format
, ...) {
599 _cleanup_free_
char *p
= NULL
;
605 va_start(ap
, format
);
606 r
= vasprintf(&p
, format
, ap
);
613 return sd_pid_notify(pid
, unset_environment
, p
);
616 _public_
int sd_notifyf(int unset_environment
, const char *format
, ...) {
617 _cleanup_free_
char *p
= NULL
;
623 va_start(ap
, format
);
624 r
= vasprintf(&p
, format
, ap
);
631 return sd_pid_notify(0, unset_environment
, p
);
634 _public_
int sd_booted(void) {
635 /* We test whether the runtime unit file directory has been
636 * created. This takes place in mount-setup.c, so is
637 * guaranteed to happen very early during boot. */
639 return laccess("/run/systemd/system/", F_OK
) >= 0;
642 _public_
int sd_watchdog_enabled(int unset_environment
, uint64_t *usec
) {
643 const char *s
, *p
= ""; /* p is set to dummy value to do unsetting */
647 s
= getenv("WATCHDOG_USEC");
651 r
= safe_atou64(s
, &u
);
654 if (u
<= 0 || u
>= USEC_INFINITY
) {
659 p
= getenv("WATCHDOG_PID");
663 r
= parse_pid(p
, &pid
);
667 /* Is this for us? */
668 if (getpid_cached() != pid
) {
680 if (unset_environment
&& s
)
681 unsetenv("WATCHDOG_USEC");
682 if (unset_environment
&& p
)
683 unsetenv("WATCHDOG_PID");