socket-util: move remaining socket-related calls from util.[ch] to socket-util.[ch]
This commit is contained in:
parent
58ce77339c
commit
2583fbea8e
|
@ -23,20 +23,22 @@
|
|||
#include <errno.h>
|
||||
#include <net/if.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "formats-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing.h"
|
||||
#include "path-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
char *e, *n;
|
||||
|
@ -749,3 +751,183 @@ bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
|
||||
value = (int) n;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_inc_rcvbuf(int fd, size_t n) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
|
||||
value = (int) n;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
|
||||
return -errno;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char* const ip_tos_table[] = {
|
||||
[IPTOS_LOWDELAY] = "low-delay",
|
||||
[IPTOS_THROUGHPUT] = "throughput",
|
||||
[IPTOS_RELIABILITY] = "reliability",
|
||||
[IPTOS_LOWCOST] = "low-cost",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred) {
|
||||
socklen_t n = sizeof(struct ucred);
|
||||
struct ucred u;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ucred);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (n != sizeof(struct ucred))
|
||||
return -EIO;
|
||||
|
||||
/* Check if the data is actually useful and not suppressed due
|
||||
* to namespacing issues */
|
||||
if (u.pid <= 0)
|
||||
return -ENODATA;
|
||||
if (u.uid == UID_INVALID)
|
||||
return -ENODATA;
|
||||
if (u.gid == GID_INVALID)
|
||||
return -ENODATA;
|
||||
|
||||
*ucred = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getpeersec(int fd, char **ret) {
|
||||
socklen_t n = 64;
|
||||
char *s;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
|
||||
if (errno != ERANGE)
|
||||
return -errno;
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (isempty(s)) {
|
||||
free(s);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_one_fd(int transport_fd, int fd, int flags) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
assert(transport_fd >= 0);
|
||||
assert(fd >= 0);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&mh);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
|
||||
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_one_fd(int transport_fd, int flags) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg, *found = NULL;
|
||||
|
||||
assert(transport_fd >= 0);
|
||||
|
||||
/*
|
||||
* Receive a single FD via @transport_fd. We don't care for
|
||||
* the transport-type. We retrieve a single FD at most, so for
|
||||
* packet-based transports, the caller must ensure to send
|
||||
* only a single FD per packet. This is best used in
|
||||
* combination with send_one_fd().
|
||||
*/
|
||||
|
||||
if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
|
||||
return -errno;
|
||||
|
||||
CMSG_FOREACH(cmsg, &mh) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
assert(!found);
|
||||
found = cmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cmsg_close_all(&mh);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return *(int*) CMSG_DATA(found);
|
||||
}
|
||||
|
|
|
@ -115,3 +115,15 @@ int netlink_family_to_string_alloc(int b, char **s);
|
|||
int netlink_family_from_string(const char *s) _pure_;
|
||||
|
||||
bool sockaddr_equal(const union sockaddr_union *a, const union sockaddr_union *b);
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n);
|
||||
int fd_inc_rcvbuf(int fd, size_t n);
|
||||
|
||||
int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
int send_one_fd(int transport_fd, int fd, int flags);
|
||||
int receive_one_fd(int transport_fd, int flags);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "io-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
|
|
181
src/basic/util.c
181
src/basic/util.c
|
@ -32,7 +32,6 @@
|
|||
#include <linux/oom.h>
|
||||
#include <linux/sched.h>
|
||||
#include <locale.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <poll.h>
|
||||
#include <pwd.h>
|
||||
#include <sched.h>
|
||||
|
@ -2271,15 +2270,6 @@ static const char* const rlimit_table[_RLIMIT_MAX] = {
|
|||
|
||||
DEFINE_STRING_TABLE_LOOKUP(rlimit, int);
|
||||
|
||||
static const char* const ip_tos_table[] = {
|
||||
[IPTOS_LOWDELAY] = "low-delay",
|
||||
[IPTOS_THROUGHPUT] = "throughput",
|
||||
[IPTOS_RELIABILITY] = "reliability",
|
||||
[IPTOS_LOWCOST] = "low-cost",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
|
||||
|
||||
bool kexec_loaded(void) {
|
||||
bool loaded = false;
|
||||
char *s;
|
||||
|
@ -2362,41 +2352,6 @@ void* memdup(const void *p, size_t l) {
|
|||
return r;
|
||||
}
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
|
||||
value = (int) n;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUFFORCE, &value, sizeof(value)) < 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof(value)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd_inc_rcvbuf(int fd, size_t n) {
|
||||
int r, value;
|
||||
socklen_t l = sizeof(value);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, &l);
|
||||
if (r >= 0 && l == sizeof(value) && (size_t) value >= n*2)
|
||||
return 0;
|
||||
|
||||
/* If we have the privileges we will ignore the kernel limit. */
|
||||
|
||||
value = (int) n;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &value, sizeof(value)) < 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof(value)) < 0)
|
||||
return -errno;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
pid_t parent_pid, agent_pid;
|
||||
|
@ -3264,73 +3219,6 @@ int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int
|
|||
return reset_uid_gid();
|
||||
}
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred) {
|
||||
socklen_t n = sizeof(struct ucred);
|
||||
struct ucred u;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ucred);
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &u, &n);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (n != sizeof(struct ucred))
|
||||
return -EIO;
|
||||
|
||||
/* Check if the data is actually useful and not suppressed due
|
||||
* to namespacing issues */
|
||||
if (u.pid <= 0)
|
||||
return -ENODATA;
|
||||
if (u.uid == UID_INVALID)
|
||||
return -ENODATA;
|
||||
if (u.gid == GID_INVALID)
|
||||
return -ENODATA;
|
||||
|
||||
*ucred = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getpeersec(int fd, char **ret) {
|
||||
socklen_t n = 64;
|
||||
char *s;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
|
||||
if (errno != ERANGE)
|
||||
return -errno;
|
||||
|
||||
s = new0(char, n);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
|
||||
if (r < 0) {
|
||||
free(s);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (isempty(s)) {
|
||||
free(s);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
*ret = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is much like like mkostemp() but is subject to umask(). */
|
||||
int mkostemp_safe(char *pattern, int flags) {
|
||||
_cleanup_umask_ mode_t u;
|
||||
|
@ -4342,75 +4230,6 @@ int fgetxattr_malloc(int fd, const char *name, char **value) {
|
|||
}
|
||||
}
|
||||
|
||||
int send_one_fd(int transport_fd, int fd, int flags) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
assert(transport_fd >= 0);
|
||||
assert(fd >= 0);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&mh);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
|
||||
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
if (sendmsg(transport_fd, &mh, MSG_NOSIGNAL | flags) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_one_fd(int transport_fd, int flags) {
|
||||
union {
|
||||
struct cmsghdr cmsghdr;
|
||||
uint8_t buf[CMSG_SPACE(sizeof(int))];
|
||||
} control = {};
|
||||
struct msghdr mh = {
|
||||
.msg_control = &control,
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
struct cmsghdr *cmsg, *found = NULL;
|
||||
|
||||
assert(transport_fd >= 0);
|
||||
|
||||
/*
|
||||
* Receive a single FD via @transport_fd. We don't care for
|
||||
* the transport-type. We retrieve a single FD at most, so for
|
||||
* packet-based transports, the caller must ensure to send
|
||||
* only a single FD per packet. This is best used in
|
||||
* combination with send_one_fd().
|
||||
*/
|
||||
|
||||
if (recvmsg(transport_fd, &mh, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC | flags) < 0)
|
||||
return -errno;
|
||||
|
||||
CMSG_FOREACH(cmsg, &mh) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
|
||||
assert(!found);
|
||||
found = cmsg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
cmsg_close_all(&mh);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return *(int*) CMSG_DATA(found);
|
||||
}
|
||||
|
||||
void nop_signal_handler(int sig) {
|
||||
/* nothing here */
|
||||
}
|
||||
|
|
|
@ -330,9 +330,6 @@ int sched_policy_from_string(const char *s);
|
|||
const char *rlimit_to_string(int i) _const_;
|
||||
int rlimit_from_string(const char *s) _pure_;
|
||||
|
||||
int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
||||
extern int saved_argc;
|
||||
extern char **saved_argv;
|
||||
|
||||
|
@ -344,9 +341,6 @@ char *format_bytes(char *buf, size_t l, uint64_t t);
|
|||
|
||||
void* memdup(const void *p, size_t l) _alloc_(2);
|
||||
|
||||
int fd_inc_sndbuf(int fd, size_t n);
|
||||
int fd_inc_rcvbuf(int fd, size_t n);
|
||||
|
||||
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...);
|
||||
|
||||
int setrlimit_closest(int resource, const struct rlimit *rlim);
|
||||
|
@ -611,9 +605,6 @@ int container_get_leader(const char *machine, pid_t *pid);
|
|||
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd);
|
||||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
int getpeersec(int fd, char **ret);
|
||||
|
||||
int mkostemp_safe(char *pattern, int flags);
|
||||
int open_tmpfile(const char *path, int flags);
|
||||
|
||||
|
@ -700,9 +691,6 @@ int mount_move_root(const char *path);
|
|||
int getxattr_malloc(const char *path, const char *name, char **value, bool allow_symlink);
|
||||
int fgetxattr_malloc(int fd, const char *name, char **value);
|
||||
|
||||
int send_one_fd(int transport_fd, int fd, int flags);
|
||||
int receive_one_fd(int transport_fd, int flags);
|
||||
|
||||
void nop_signal_handler(int sig);
|
||||
|
||||
int version(void);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "namespace.h"
|
||||
#include "path-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "io-util.h"
|
||||
#include "login-util.h"
|
||||
#include "macro.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "missing.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static int sd_netlink_new(sd_netlink **ret) {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "local-addresses.h"
|
||||
#include "netlink-util.h"
|
||||
#include "nspawn-expose-ports.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#include "seccomp-util.h"
|
||||
#endif
|
||||
#include "signal-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
|
|
Loading…
Reference in New Issue