11b56dabaaa294349d326b90f86e4bef7c22f1d96Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
3dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering/***
4dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  Copyright 2010 Lennart Poettering
5dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
6dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  Permission is hereby granted, free of charge, to any person
7dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  obtaining a copy of this software and associated documentation files
8dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  (the "Software"), to deal in the Software without restriction,
9dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  including without limitation the rights to use, copy, modify, merge,
10dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  publish, distribute, sublicense, and/or sell copies of the Software,
11dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  and to permit persons to whom the Software is furnished to do so,
12dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  subject to the following conditions:
13dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
14dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  The above copyright notice and this permission notice shall be
15dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  included in all copies or substantial portions of the Software.
16dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
17dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering  SOFTWARE.
25dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering***/
26dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
27dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#ifndef _GNU_SOURCE
28dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#define _GNU_SOURCE
29dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#endif
30dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
31dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <sys/types.h>
32dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <sys/stat.h>
33dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <sys/socket.h>
34dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <sys/un.h>
3528c78cdf3df937d1cd72e3c358f7afa129a8cdabJaikumar Ganesh#include <fcntl.h>
36dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <netinet/in.h>
37dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <stdlib.h>
38dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <errno.h>
39dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <unistd.h>
40dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <string.h>
41dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <stdarg.h>
42dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include <stdio.h>
43dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
44dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#include "sd-daemon.h"
45dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
46dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_listen_fds(int unset_environment) {
47dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
48dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
49dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 0;
50dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#else
51dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int r, fd;
52dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        const char *e;
53dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        char *p = NULL;
54dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        unsigned long l;
55dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
56dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!(e = getenv("LISTEN_PID"))) {
57dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = 0;
58dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
59dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
60dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
61dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        errno = 0;
62dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        l = strtoul(e, &p, 10);
63dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
64dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (errno != 0) {
65dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -errno;
66dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
67dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
68dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
69dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!p || *p || l <= 0) {
70dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -EINVAL;
71dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
72dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
73dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
74dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        /* Is this for us? */
75dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (getpid() != (pid_t) l) {
76dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = 0;
77dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
78dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
79dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
80dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!(e = getenv("LISTEN_FDS"))) {
81dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = 0;
82dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
83dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
84dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
85dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        errno = 0;
86dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        l = strtoul(e, &p, 10);
87dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
88dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (errno != 0) {
89dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -errno;
90dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
91dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
92dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
93dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!p || *p) {
94dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -EINVAL;
95dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
96dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
97dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
98dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + (int) l; fd ++) {
99dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                int flags;
100dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
101dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if ((flags = fcntl(fd, F_GETFD)) < 0) {
102dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        r = -errno;
103dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        goto finish;
104dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                }
105dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
106dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (flags & FD_CLOEXEC)
107dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        continue;
108dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
109dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
110dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        r = -errno;
111dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        goto finish;
112dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                }
113dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
114dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
115dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        r = (int) l;
116dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
117dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringfinish:
118dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (unset_environment) {
119dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                unsetenv("LISTEN_PID");
120dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                unsetenv("LISTEN_FDS");
121dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
122dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
123dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return r;
124dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#endif
125dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
126dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
127dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_is_fifo(int fd, const char *path) {
128dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct stat st_fd;
129dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
130dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (fd < 0)
131dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
132dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
133dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&st_fd, 0, sizeof(st_fd));
134dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (fstat(fd, &st_fd) < 0)
135dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -errno;
136dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
137dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!S_ISFIFO(st_fd.st_mode))
138dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
139dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
140dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (path) {
141dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                struct stat st_path;
142dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
143dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                memset(&st_path, 0, sizeof(st_path));
144dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (stat(path, &st_path) < 0) {
145dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
146dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        if (errno == ENOENT || errno == ENOTDIR)
147dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                return 0;
148dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
149dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -errno;
150dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                }
151dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
152dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return
153dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        st_path.st_dev == st_fd.st_dev &&
154dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        st_path.st_ino == st_fd.st_ino;
155dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
156dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
157dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 1;
158dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
159dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
160dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringstatic int sd_is_socket_internal(int fd, int type, int listening) {
161dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct stat st_fd;
162dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
163dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (fd < 0 || type < 0)
164dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
165dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
166dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (fstat(fd, &st_fd) < 0)
167dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -errno;
168dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
169dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!S_ISSOCK(st_fd.st_mode))
170dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
171dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
172dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (type != 0) {
173dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                int other_type = 0;
174dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                socklen_t l = sizeof(other_type);
175dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
176dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &other_type, &l) < 0)
177dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -errno;
178dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
179dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (l != sizeof(other_type))
180dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -EINVAL;
181dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
182dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (other_type != type)
183dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return 0;
184dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
185dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
186dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (listening >= 0) {
187dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                int accepting = 0;
188dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                socklen_t l = sizeof(accepting);
189dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
190dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &accepting, &l) < 0)
191dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -errno;
192dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
193dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (l != sizeof(accepting))
194dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -EINVAL;
195dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
196dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (!accepting != !listening)
197dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return 0;
198dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
199dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
200dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 1;
201dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
202dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
203dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringunion sockaddr_union {
204dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct sockaddr sa;
205dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct sockaddr_in in4;
206dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct sockaddr_in6 in6;
207dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct sockaddr_un un;
208dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct sockaddr_storage storage;
209dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering};
210dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
211dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_is_socket(int fd, int family, int type, int listening) {
212dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int r;
213dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
214dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (family < 0)
215dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
216dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
217dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
218dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return r;
219dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
220dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (family > 0) {
221dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                union sockaddr_union sockaddr;
222dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                socklen_t l;
223dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
224dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                memset(&sockaddr, 0, sizeof(sockaddr));
225dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                l = sizeof(sockaddr);
226dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
227dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (getsockname(fd, &sockaddr.sa, &l) < 0)
228dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -errno;
229dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
230dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (l < sizeof(sa_family_t))
231dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return -EINVAL;
232dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
233dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return sockaddr.sa.sa_family == family;
234dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
235dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
236dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 1;
237dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
238dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
239dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_is_socket_inet(int fd, int family, int type, int listening, uint16_t port) {
240dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        union sockaddr_union sockaddr;
241dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        socklen_t l;
242dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int r;
243dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
244dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (family != 0 && family != AF_INET && family != AF_INET6)
245dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
246dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
247dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
248dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return r;
249dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
250dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&sockaddr, 0, sizeof(sockaddr));
251dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        l = sizeof(sockaddr);
252dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
253dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (getsockname(fd, &sockaddr.sa, &l) < 0)
254dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -errno;
255dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
256dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (l < sizeof(sa_family_t))
257dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
258dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
259dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (sockaddr.sa.sa_family != AF_INET &&
260dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering            sockaddr.sa.sa_family != AF_INET6)
261dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
262dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
263dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (family > 0)
264dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (sockaddr.sa.sa_family != family)
265dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return 0;
266dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
267dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (port > 0) {
268dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (sockaddr.sa.sa_family == AF_INET) {
269dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        if (l < sizeof(struct sockaddr_in))
270dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                return -EINVAL;
271dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
272dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return htons(port) == sockaddr.in4.sin_port;
273dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                } else {
274dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        if (l < sizeof(struct sockaddr_in6))
275dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                return -EINVAL;
276dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
277dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return htons(port) == sockaddr.in6.sin6_port;
278dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                }
279dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
280dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
281dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 1;
282dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
283dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
284dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_is_socket_unix(int fd, int type, int listening, const char *path, size_t length) {
285dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        union sockaddr_union sockaddr;
286dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        socklen_t l;
287dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int r;
288dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
289dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if ((r = sd_is_socket_internal(fd, type, listening)) <= 0)
290dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return r;
291dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
292dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&sockaddr, 0, sizeof(sockaddr));
293dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        l = sizeof(sockaddr);
294dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
295dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (getsockname(fd, &sockaddr.sa, &l) < 0)
296dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -errno;
297dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
298dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (l < sizeof(sa_family_t))
299dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -EINVAL;
300dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
301dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (sockaddr.sa.sa_family != AF_UNIX)
302dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
303dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
304dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (path) {
305dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (length <= 0)
306dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        length = strlen(path);
307dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
308dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (length <= 0)
309dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        /* Unnamed socket */
310dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return l == sizeof(sa_family_t);
311dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
312dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                if (path[0])
313dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        /* Normal path socket */
314dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return
315dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                (l >= sizeof(sa_family_t) + length + 1) &&
316dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                memcmp(path, sockaddr.un.sun_path, length+1) == 0;
317dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                else
318dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        /* Abstract namespace socket */
319dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                        return
320dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                (l == sizeof(sa_family_t) + length) &&
321dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                                memcmp(path, sockaddr.un.sun_path, length) == 0;
322dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
323dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
324dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 1;
325dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
326dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
327dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_notify(int unset_environment, const char *state) {
328ff2325c92c411e6718ae38d6976f54580ed57e86Lennart Poettering#if defined(DISABLE_SYSTEMD) || !defined(__linux__) || !defined(SOCK_CLOEXEC)
329dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 0;
330dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#else
331dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int fd = -1, r;
332dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct msghdr msghdr;
333dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct iovec iovec;
334dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        union sockaddr_union sockaddr;
335dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        const char *e;
336dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
337dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!state) {
338dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -EINVAL;
339dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
340dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
341dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
342dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (!(e = getenv("NOTIFY_SOCKET")))
343dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
344dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
345dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        /* Must be an abstract socket, or an absolute path */
346dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if ((e[0] != '@' && e[0] != '/') || e[1] == 0) {
347dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -EINVAL;
348dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
349dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
350dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
351dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0) {
352dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -errno;
353dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
354dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
355dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
356dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&sockaddr, 0, sizeof(sockaddr));
357dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        sockaddr.sa.sa_family = AF_UNIX;
358dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path));
359dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
360dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (sockaddr.un.sun_path[0] == '@')
361dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                sockaddr.un.sun_path[0] = 0;
362dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
363dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&iovec, 0, sizeof(iovec));
364dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        iovec.iov_base = (char*) state;
365dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        iovec.iov_len = strlen(state);
366dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
367dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        memset(&msghdr, 0, sizeof(msghdr));
368dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        msghdr.msg_name = &sockaddr;
369265a3bb04a46d889b89ff0a5f6d4c93df092e0fbLennart Poettering        msghdr.msg_namelen = sizeof(sa_family_t) + strlen(e);
370265a3bb04a46d889b89ff0a5f6d4c93df092e0fbLennart Poettering
371265a3bb04a46d889b89ff0a5f6d4c93df092e0fbLennart Poettering        if (msghdr.msg_namelen > sizeof(struct sockaddr_un))
372265a3bb04a46d889b89ff0a5f6d4c93df092e0fbLennart Poettering                msghdr.msg_namelen = sizeof(struct sockaddr_un);
373265a3bb04a46d889b89ff0a5f6d4c93df092e0fbLennart Poettering
374dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        msghdr.msg_iov = &iovec;
375dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        msghdr.msg_iovlen = 1;
376dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
377dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
378dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                r = -errno;
379dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                goto finish;
380dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        }
381dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
382dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        r = 1;
383dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
384dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringfinish:
385dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (unset_environment)
386dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                unsetenv("NOTIFY_SOCKET");
387dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
388dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (fd >= 0)
389dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                close(fd);
390dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
391dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return r;
392dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#endif
393dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
394dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
395dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_notifyf(int unset_environment, const char *format, ...) {
396dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
397dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 0;
398dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#else
399dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        va_list ap;
400dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        char *p = NULL;
401dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        int r;
402dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
403dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        va_start(ap, format);
404dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        r = vasprintf(&p, format, ap);
405dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        va_end(ap);
406dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
407dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        if (r < 0 || !p)
408dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return -ENOMEM;
409dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
410dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        r = sd_notify(unset_environment, p);
411dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        free(p);
412dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
413dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return r;
414dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#endif
415dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
416dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
417dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poetteringint sd_booted(void) {
418dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#if defined(DISABLE_SYSTEMD) || !defined(__linux__)
419dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return 0;
420dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#else
421dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
422dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        struct stat a, b;
423dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
424dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        /* We simply test whether the systemd cgroup hierarchy is
425dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering         * mounted */
426dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
4271b56dabaaa294349d326b90f86e4bef7c22f1d96Lennart Poettering        if (lstat("/sys/fs/cgroup", &a) < 0)
428dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
429dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
4301b56dabaaa294349d326b90f86e4bef7c22f1d96Lennart Poettering        if (lstat("/sys/fs/cgroup/systemd", &b) < 0)
431dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering                return 0;
432dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering
433dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering        return a.st_dev != b.st_dev;
434dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering#endif
435dd31130a971593b5e20a1c4cb04f93c2aae90c84Lennart Poettering}
436