summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--man/systemd.netdev.xml9
-rw-r--r--src/basic/fileio.c25
-rw-r--r--src/basic/parse-util.c18
-rw-r--r--src/basic/parse-util.h2
-rw-r--r--src/basic/process-util.h5
-rw-r--r--src/basic/set.h8
-rw-r--r--src/core/dbus-execute.c2
-rw-r--r--src/core/load-fragment.c32
-rw-r--r--src/core/main.c1
-rw-r--r--src/core/service.c36
-rw-r--r--src/core/socket.c324
-rw-r--r--src/core/socket.h10
-rw-r--r--src/journal-remote/journal-gatewayd.c3
-rw-r--r--src/journal-remote/journal-remote.c4
-rw-r--r--src/network/networkd-brvlan.c20
-rw-r--r--src/network/networkd-brvlan.h1
-rw-r--r--src/network/networkd-link.c5
-rw-r--r--src/network/networkd-netdev-bridge.c7
-rw-r--r--src/network/networkd-netdev-bridge.h1
-rw-r--r--src/network/networkd-netdev-gperf.gperf1
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.h1
-rw-r--r--src/run/run.c8
-rw-r--r--src/shared/bus-unit-util.c12
-rw-r--r--src/test/test-parse-util.c29
25 files changed, 315 insertions, 251 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index a5c6f0fa40..e56708a648 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -343,8 +343,15 @@
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>STP=</varname></term>
+ <listitem>
+ <para>A boolean. This enables the bridge's Spanning Tree Protocol (STP). When unset,
+ the kernel's default setting applies.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
-
</refsect1>
<refsect1>
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index 6114bf3315..d642f3daea 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -47,6 +47,8 @@
#include "umask-util.h"
#include "utf8.h"
+#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
+
int write_string_stream(FILE *f, const char *line, bool enforce_newline) {
assert(f);
@@ -230,7 +232,7 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
if (S_ISREG(st.st_mode)) {
/* Safety check */
- if (st.st_size > 4*1024*1024)
+ if (st.st_size > READ_FULL_BYTES_MAX)
return -E2BIG;
/* Start with the right file size, but be prepared for
@@ -245,26 +247,31 @@ int read_full_stream(FILE *f, char **contents, size_t *size) {
char *t;
size_t k;
- t = realloc(buf, n+1);
+ t = realloc(buf, n + 1);
if (!t)
return -ENOMEM;
buf = t;
k = fread(buf + l, 1, n - l, f);
+ if (k > 0)
+ l += k;
- if (k <= 0) {
- if (ferror(f))
- return -errno;
+ if (ferror(f))
+ return -errno;
+ if (feof(f))
break;
- }
- l += k;
- n *= 2;
+ /* We aren't expecting fread() to return a short read outside
+ * of (error && eof), assert buffer is full and enlarge buffer.
+ */
+ assert(l == n);
/* Safety check */
- if (n > 4*1024*1024)
+ if (n >= READ_FULL_BYTES_MAX)
return -E2BIG;
+
+ n = MIN(n * 2, READ_FULL_BYTES_MAX);
}
buf[l] = 0;
diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c
index 11849ade0b..c98815b9bc 100644
--- a/src/basic/parse-util.c
+++ b/src/basic/parse-util.c
@@ -29,6 +29,7 @@
#include "extract-word.h"
#include "macro.h"
#include "parse-util.h"
+#include "process-util.h"
#include "string-util.h"
int parse_boolean(const char *v) {
@@ -551,10 +552,25 @@ int parse_percent_unbounded(const char *p) {
}
int parse_percent(const char *p) {
- int v = parse_percent_unbounded(p);
+ int v;
+ v = parse_percent_unbounded(p);
if (v > 100)
return -ERANGE;
return v;
}
+
+int parse_nice(const char *p, int *ret) {
+ int n, r;
+
+ r = safe_atoi(p, &n);
+ if (r < 0)
+ return r;
+
+ if (!nice_is_valid(n))
+ return -ERANGE;
+
+ *ret = n;
+ return 0;
+}
diff --git a/src/basic/parse-util.h b/src/basic/parse-util.h
index f0fa5f9752..461e1cd4d8 100644
--- a/src/basic/parse-util.h
+++ b/src/basic/parse-util.h
@@ -108,3 +108,5 @@ int parse_fractional_part_u(const char **s, size_t digits, unsigned *res);
int parse_percent_unbounded(const char *p);
int parse_percent(const char *p);
+
+int parse_nice(const char *p, int *ret);
diff --git a/src/basic/process-util.h b/src/basic/process-util.h
index 9f75088796..2568e3834f 100644
--- a/src/basic/process-util.h
+++ b/src/basic/process-util.h
@@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
+#include <sys/resource.h>
#include "formats-util.h"
#include "macro.h"
@@ -103,3 +104,7 @@ int sched_policy_from_string(const char *s);
void valgrind_summary_hack(void);
int pid_compare_func(const void *a, const void *b);
+
+static inline bool nice_is_valid(int n) {
+ return n >= PRIO_MIN && n < PRIO_MAX;
+}
diff --git a/src/basic/set.h b/src/basic/set.h
index 12f64a8c57..a5f8beb0c4 100644
--- a/src/basic/set.h
+++ b/src/basic/set.h
@@ -23,8 +23,8 @@
#include "hashmap.h"
#include "macro.h"
-Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
+Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)
static inline Set *set_free(Set *s) {
internal_hashmap_free(HASHMAP_BASE(s));
@@ -42,8 +42,8 @@ static inline Set *set_copy(Set *s) {
return (Set*) internal_hashmap_copy(HASHMAP_BASE(s));
}
-int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
-#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
+int internal_set_ensure_allocated(Set **s, const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
+#define set_ensure_allocated(h, ops) internal_set_ensure_allocated(h, ops HASHMAP_DEBUG_SRC_ARGS)
int set_put(Set *s, const void *key);
/* no set_update */
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 9c50cd93e5..346c8b973e 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -935,7 +935,7 @@ int bus_exec_context_set_transient_property(
if (r < 0)
return r;
- if (n < PRIO_MIN || n >= PRIO_MAX)
+ if (!nice_is_valid(n))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
if (mode != UNIT_CHECK) {
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index d5f035b67f..420f368689 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -491,16 +491,17 @@ int config_parse_socket_bind(const char *unit,
return 0;
}
-int config_parse_exec_nice(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata) {
+int config_parse_exec_nice(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
ExecContext *c = data;
int priority, r;
@@ -510,14 +511,13 @@ int config_parse_exec_nice(const char *unit,
assert(rvalue);
assert(data);
- r = safe_atoi(rvalue, &priority);
+ r = parse_nice(rvalue, &priority);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue);
- return 0;
- }
+ if (r == -ERANGE)
+ log_syntax(unit, LOG_ERR, filename, line, r, "Nice priority out of range, ignoring: %s", rvalue);
+ else
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse nice priority, ignoring: %s", rvalue);
- if (priority < PRIO_MIN || priority >= PRIO_MAX) {
- log_syntax(unit, LOG_ERR, filename, line, 0, "Nice priority out of range, ignoring: %s", rvalue);
return 0;
}
diff --git a/src/core/main.c b/src/core/main.c
index 094bbef964..02324d325e 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1614,6 +1614,7 @@ int main(int argc, char *argv[]) {
retval = version();
goto finish;
} else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
+ pager_open(arg_no_pager, false);
unit_dump_config_items(stdout);
retval = EXIT_SUCCESS;
goto finish;
diff --git a/src/core/service.c b/src/core/service.c
index c21653f5fa..4a37702f52 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -761,6 +761,11 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
prefix, s->bus_name,
prefix, yes_no(s->bus_name_good));
+ if (UNIT_ISSET(s->accept_socket))
+ fprintf(f,
+ "%sAccept Socket: %s\n",
+ prefix, UNIT_DEREF(s->accept_socket)->id);
+
kill_context_dump(&s->kill_context, f, prefix);
exec_context_dump(&s->exec_context, f, prefix);
@@ -1036,6 +1041,20 @@ static int service_coldplug(Unit *u) {
if (!IN_SET(s->deserialized_state, SERVICE_DEAD, SERVICE_FAILED, SERVICE_AUTO_RESTART))
(void) unit_setup_dynamic_creds(u);
+ if (UNIT_ISSET(s->accept_socket)) {
+ Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket));
+
+ if (socket->max_connections_per_source > 0) {
+ SocketPeer *peer;
+
+ /* Make a best-effort attempt at bumping the connection count */
+ if (socket_acquire_peer(socket, s->socket_fd, &peer) > 0) {
+ socket_peer_unref(s->peer);
+ s->peer = peer;
+ }
+ }
+ }
+
service_set_state(s, s->deserialized_state);
return 0;
}
@@ -2119,6 +2138,12 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
if (r < 0)
return r;
+ if (UNIT_ISSET(s->accept_socket)) {
+ r = unit_serialize_item(u, f, "accept-socket", UNIT_DEREF(s->accept_socket)->id);
+ if (r < 0)
+ return r;
+ }
+
r = unit_serialize_item_fd(u, f, fds, "socket-fd", s->socket_fd);
if (r < 0)
return r;
@@ -2249,6 +2274,17 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
s->control_command_id = id;
s->control_command = s->exec_command[id];
}
+ } else if (streq(key, "accept-socket")) {
+ Unit *socket;
+
+ r = manager_load_unit(u->manager, value, NULL, NULL, &socket);
+ if (r < 0)
+ log_unit_debug_errno(u, r, "Failed to load accept-socket unit: %s", value);
+ else {
+ unit_ref_set(&s->accept_socket, socket);
+ SOCKET(socket)->n_connections++;
+ }
+
} else if (streq(key, "socket-fd")) {
int fd;
diff --git a/src/core/socket.c b/src/core/socket.c
index c919e89b7d..50872e8366 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -59,6 +59,13 @@
#include "user-util.h"
#include "in-addr-util.h"
+struct SocketPeer {
+ unsigned n_ref;
+
+ Socket *socket;
+ union sockaddr_union peer;
+};
+
static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
[SOCKET_DEAD] = UNIT_INACTIVE,
[SOCKET_START_PRE] = UNIT_ACTIVATING,
@@ -78,9 +85,6 @@ static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata);
static int socket_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
-SocketPeer *socket_peer_new(void);
-int socket_find_peer(Socket *s, int fd, SocketPeer **p);
-
static void socket_init(Unit *u) {
Socket *s = SOCKET(u);
@@ -151,10 +155,10 @@ static void socket_done(Unit *u) {
socket_free_ports(s);
- while ((p = hashmap_steal_first(s->peers_by_address)))
+ while ((p = set_steal_first(s->peers_by_address)))
p->socket = NULL;
- s->peers_by_address = hashmap_free(s->peers_by_address);
+ s->peers_by_address = set_free(s->peers_by_address);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
exec_command_free_array(s->exec_command, _SOCKET_EXEC_COMMAND_MAX);
@@ -482,10 +486,11 @@ static void peer_address_hash_func(const void *p, struct siphash *state) {
const SocketPeer *s = p;
assert(s);
+ assert(IN_SET(s->peer.sa.sa_family, AF_INET, AF_INET6));
if (s->peer.sa.sa_family == AF_INET)
siphash24_compress(&s->peer.in.sin_addr, sizeof(s->peer.in.sin_addr), state);
- else if (s->peer.sa.sa_family == AF_INET6)
+ else
siphash24_compress(&s->peer.in6.sin6_addr, sizeof(s->peer.in6.sin6_addr), state);
}
@@ -503,8 +508,7 @@ static int peer_address_compare_func(const void *a, const void *b) {
case AF_INET6:
return memcmp(&x->peer.in6.sin6_addr, &y->peer.in6.sin6_addr, sizeof(x->peer.in6.sin6_addr));
}
-
- return -1;
+ assert_not_reached("Black sheep in the family!");
}
const struct hash_ops peer_address_hash_ops = {
@@ -519,7 +523,7 @@ static int socket_load(Unit *u) {
assert(u);
assert(u->load_state == UNIT_STUB);
- r = hashmap_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
+ r = set_ensure_allocated(&s->peers_by_address, &peer_address_hash_ops);
if (r < 0)
return r;
@@ -537,6 +541,87 @@ static int socket_load(Unit *u) {
return socket_verify(s);
}
+static SocketPeer *socket_peer_new(void) {
+ SocketPeer *p;
+
+ p = new0(SocketPeer, 1);
+ if (!p)
+ return NULL;
+
+ p->n_ref = 1;
+
+ return p;
+}
+
+SocketPeer *socket_peer_ref(SocketPeer *p) {
+ if (!p)
+ return NULL;
+
+ assert(p->n_ref > 0);
+ p->n_ref++;
+
+ return p;
+}
+
+SocketPeer *socket_peer_unref(SocketPeer *p) {
+ if (!p)
+ return NULL;
+
+ assert(p->n_ref > 0);
+
+ p->n_ref--;
+
+ if (p->n_ref > 0)
+ return NULL;
+
+ if (p->socket)
+ set_remove(p->socket->peers_by_address, p);
+
+ return mfree(p);
+}
+
+int socket_acquire_peer(Socket *s, int fd, SocketPeer **p) {
+ _cleanup_(socket_peer_unrefp) SocketPeer *remote = NULL;
+ SocketPeer sa = {}, *i;
+ socklen_t salen = sizeof(sa.peer);
+ int r;
+
+ assert(fd >= 0);
+ assert(s);
+
+ r = getpeername(fd, &sa.peer.sa, &salen);
+ if (r < 0)
+ return log_error_errno(errno, "getpeername failed: %m");
+
+ if (!IN_SET(sa.peer.sa.sa_family, AF_INET, AF_INET6)) {
+ *p = NULL;
+ return 0;
+ }
+
+ i = set_get(s->peers_by_address, &sa);
+ if (i) {
+ *p = socket_peer_ref(i);
+ return 1;
+ }
+
+ remote = socket_peer_new();
+ if (!remote)
+ return log_oom();
+
+ remote->peer = sa.peer;
+
+ r = set_put(s->peers_by_address, remote);
+ if (r < 0)
+ return r;
+
+ remote->socket = s;
+
+ *p = remote;
+ remote = NULL;
+
+ return 1;
+}
+
_const_ static const char* listen_lookup(int family, int type) {
if (family == AF_NETLINK)
@@ -2100,22 +2185,26 @@ static void socket_enter_running(Socket *s, int cfd) {
Service *service;
if (s->n_connections >= s->max_connections) {
- log_unit_warning(UNIT(s), "Too many incoming connections (%u), refusing connection attempt.", s->n_connections);
+ log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.",
+ s->n_connections);
safe_close(cfd);
return;
}
if (s->max_connections_per_source > 0) {
- r = socket_find_peer(s, cfd, &p);
+ r = socket_acquire_peer(s, cfd, &p);
if (r < 0) {
safe_close(cfd);
return;
- }
+ } else if (r > 0 && p->n_ref > s->max_connections_per_source) {
+ _cleanup_free_ char *t = NULL;
+
+ sockaddr_pretty(&p->peer.sa, FAMILY_ADDRESS_SIZE(p->peer.sa.sa_family), true, false, &t);
- if (p->n_ref > s->max_connections_per_source) {
- log_unit_warning(UNIT(s), "Too many incoming connections (%u) from source, refusing connection attempt.", p->n_ref);
+ log_unit_warning(UNIT(s),
+ "Too many incoming connections (%u) from source %s, dropping connection.",
+ p->n_ref, strnull(t));
safe_close(cfd);
- p = NULL;
return;
}
}
@@ -2161,10 +2250,8 @@ static void socket_enter_running(Socket *s, int cfd) {
cfd = -1; /* We passed ownership of the fd to the service now. Forget it here. */
s->n_connections++;
- if (s->max_connections_per_source > 0) {
- service->peer = socket_peer_ref(p);
- p = NULL;
- }
+ service->peer = p; /* Pass ownership of the peer reference */
+ p = NULL;
r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, &error, NULL);
if (r < 0) {
@@ -2311,9 +2398,7 @@ static int socket_stop(Unit *u) {
static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
Socket *s = SOCKET(u);
- SocketPeer *k;
SocketPort *p;
- Iterator i;
int r;
assert(u);
@@ -2364,19 +2449,14 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
}
}
- HASHMAP_FOREACH(k, s->peers_by_address, i) {
- _cleanup_free_ char *t = NULL;
-
- r = sockaddr_pretty(&k->peer.sa, FAMILY_ADDRESS_SIZE(k->peer.sa.sa_family), true, true, &t);
- if (r < 0)
- return r;
-
- unit_serialize_item_format(u, f, "peer", "%u %s", k->n_ref, t);
- }
-
return 0;
}
+static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) {
+ safe_close(p->fd);
+ p->fd = fdset_remove(fds, fd);
+}
+
static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Socket *s = SOCKET(u);
@@ -2431,18 +2511,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse fifo value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
if (p->type == SOCKET_FIFO &&
- path_equal_or_files_same(p->path, value+skip))
+ path_equal_or_files_same(p->path, value+skip)) {
+ socket_port_take_fd(p, fds, fd);
break;
-
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
+ }
} else if (streq(key, "special")) {
int fd, skip = 0;
@@ -2450,18 +2525,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse special value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
if (p->type == SOCKET_SPECIAL &&
- path_equal_or_files_same(p->path, value+skip))
+ path_equal_or_files_same(p->path, value+skip)) {
+ socket_port_take_fd(p, fds, fd);
break;
-
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
+ }
} else if (streq(key, "mqueue")) {
int fd, skip = 0;
@@ -2469,18 +2539,13 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse mqueue value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
if (p->type == SOCKET_MQUEUE &&
- streq(p->path, value+skip))
+ streq(p->path, value+skip)) {
+ socket_port_take_fd(p, fds, fd);
break;
-
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
+ }
} else if (streq(key, "socket")) {
int fd, type, skip = 0;
@@ -2488,17 +2553,12 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
- if (socket_address_is(&p->address, value+skip, type))
+ if (socket_address_is(&p->address, value+skip, type)) {
+ socket_port_take_fd(p, fds, fd);
break;
-
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
+ }
} else if (streq(key, "netlink")) {
int fd, skip = 0;
@@ -2506,17 +2566,12 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
- if (socket_address_is_netlink(&p->address, value+skip))
+ if (socket_address_is_netlink(&p->address, value+skip)) {
+ socket_port_take_fd(p, fds, fd);
break;
-
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
+ }
} else if (streq(key, "ffs")) {
int fd, skip = 0;
@@ -2524,46 +2579,14 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse ffs value: %s", value);
- else {
-
+ else
LIST_FOREACH(port, p, s->ports)
if (p->type == SOCKET_USB_FUNCTION &&
- path_equal_or_files_same(p->path, value+skip))
+ path_equal_or_files_same(p->path, value+skip)) {
+ socket_port_take_fd(p, fds, fd);
break;
+ }
- if (p) {
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
- }
- }
-
- } else if (streq(key, "peer")) {
- _cleanup_(socket_peer_unrefp) SocketPeer *p;
- int n_ref, skip = 0;
- SocketAddress a;
- int r;
-
- if (sscanf(value, "%u %n", &n_ref, &skip) < 1 || n_ref < 1)
- log_unit_debug(u, "Failed to parse socket peer value: %s", value);
- else {
- r = socket_address_parse(&a, value+skip);
- if (r < 0)
- return r;
-
- p = socket_peer_new();
- if (!p)
- return log_oom();
-
- p->n_ref = n_ref;
- memcpy(&p->peer, &a.sockaddr, sizeof(a.sockaddr));
- p->socket = s;
-
- r = hashmap_put(s->peers_by_address, p, p);
- if (r < 0)
- return r;
-
- p = NULL;
- }
} else
log_unit_debug(UNIT(s), "Unknown serialization key: %s", key);
@@ -2660,83 +2683,6 @@ _pure_ static bool socket_check_gc(Unit *u) {
return s->n_connections > 0;
}
-SocketPeer *socket_peer_new(void) {
- SocketPeer *p;
-
- p = new0(SocketPeer, 1);
- if (!p)
- return NULL;
-
- p->n_ref = 1;
-
- return p;
-}
-
-SocketPeer *socket_peer_ref(SocketPeer *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
- p->n_ref++;
-
- return p;
-}
-
-SocketPeer *socket_peer_unref(SocketPeer *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
-
- p->n_ref--;
-
- if (p->n_ref > 0)
- return NULL;
-
- if (p->socket)
- (void) hashmap_remove(p->socket->peers_by_address, p);
-
- free(p);
-
- return NULL;
-}
-
-int socket_find_peer(Socket *s, int fd, SocketPeer **p) {
- _cleanup_free_ SocketPeer *remote = NULL;
- SocketPeer sa, *i;
- socklen_t salen = sizeof(sa.peer);
- int r;
-
- assert(fd >= 0);
- assert(s);
-
- r = getpeername(fd, &sa.peer.sa, &salen);
- if (r < 0)
- return log_error_errno(errno, "getpeername failed: %m");
-
- i = hashmap_get(s->peers_by_address, &sa);
- if (i) {
- *p = i;
- return 1;
- }
-
- remote = socket_peer_new();
- if (!remote)
- return log_oom();
-
- memcpy(&remote->peer, &sa.peer, sizeof(union sockaddr_union));
- remote->socket = s;
-
- r = hashmap_put(s->peers_by_address, remote, remote);
- if (r < 0)
- return r;
-
- *p = remote;
- remote = NULL;
-
- return 0;
-}
-
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
SocketPort *p = userdata;
int cfd = -1;
diff --git a/src/core/socket.h b/src/core/socket.h
index 2fe38ef2aa..89f4664510 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -80,7 +80,7 @@ struct Socket {
LIST_HEAD(SocketPort, ports);
- Hashmap *peers_by_address;
+ Set *peers_by_address;
unsigned n_accepted;
unsigned n_connections;
@@ -168,15 +168,9 @@ struct Socket {
RateLimit trigger_limit;
};
-struct SocketPeer {
- unsigned n_ref;
-
- Socket *socket;
- union sockaddr_union peer;
-};
-
SocketPeer *socket_peer_ref(SocketPeer *p);
SocketPeer *socket_peer_unref(SocketPeer *p);
+int socket_acquire_peer(Socket *s, int fd, SocketPeer **p);
DEFINE_TRIVIAL_CLEANUP_FUNC(SocketPeer*, socket_peer_unref);
diff --git a/src/journal-remote/journal-gatewayd.c b/src/journal-remote/journal-gatewayd.c
index 4ad9184993..a1627fab39 100644
--- a/src/journal-remote/journal-gatewayd.c
+++ b/src/journal-remote/journal-gatewayd.c
@@ -19,9 +19,6 @@
#include <fcntl.h>
#include <getopt.h>
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/journal-remote/journal-remote.c b/src/journal-remote/journal-remote.c
index f1ef90ed7a..80e2adb100 100644
--- a/src/journal-remote/journal-remote.c
+++ b/src/journal-remote/journal-remote.c
@@ -27,10 +27,6 @@
#include <sys/socket.h>
#include <unistd.h>
-#ifdef HAVE_GNUTLS
-#include <gnutls/gnutls.h>
-#endif
-
#include "sd-daemon.h"
#include "alloc-util.h"
diff --git a/src/network/networkd-brvlan.c b/src/network/networkd-brvlan.c
index 8bc330ebae..18ecd86858 100644
--- a/src/network/networkd-brvlan.c
+++ b/src/network/networkd-brvlan.c
@@ -257,6 +257,24 @@ static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end)
return r;
}
+int config_parse_brvlan_pvid(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata) {
+ Network *network = userdata;
+ int r;
+ uint16_t pvid;
+ r = parse_vlanid(rvalue, &pvid);
+ if (r < 0)
+ return r;
+
+ network->pvid = pvid;
+ network->use_br_vlan = true;
+
+ return 0;
+}
+
int config_parse_brvlan_vlan(const char *unit, const char *filename,
unsigned line, const char *section,
unsigned section_line, const char *lvalue,
@@ -288,6 +306,7 @@ int config_parse_brvlan_vlan(const char *unit, const char *filename,
for (; vid <= vid_end; vid++)
set_bit(vid, network->br_vid_bitmap);
}
+ network->use_br_vlan = true;
return 0;
}
@@ -325,5 +344,6 @@ int config_parse_brvlan_untagged(const char *unit, const char *filename,
set_bit(vid, network->br_untagged_bitmap);
}
}
+ network->use_br_vlan = true;
return 0;
}
diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h
index 6aa6883bfc..b37633f94f 100644
--- a/src/network/networkd-brvlan.h
+++ b/src/network/networkd-brvlan.h
@@ -25,5 +25,6 @@ typedef struct Link Link;
int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
+int config_parse_brvlan_pvid(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_brvlan_vlan(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_brvlan_untagged(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 3e10ab1e04..69ee7424ce 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1357,7 +1357,7 @@ static int link_set_flags(Link *link) {
if (link->network->arp >= 0) {
ifi_change |= IFF_NOARP;
- ifi_flags |= IFF_NOARP;
+ ifi_flags |= link->network->arp ? 0 : IFF_NOARP;
}
r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change);
@@ -2060,7 +2060,8 @@ static int link_joined(Link *link) {
log_link_error_errno(link, r, "Could not set bridge message: %m");
}
- if (link->network->bridge || streq_ptr("bridge", link->kind)) {
+ if (link->network->use_br_vlan &&
+ (link->network->bridge || streq_ptr("bridge", link->kind))) {
r = link_set_bridge_vlan(link);
if (r < 0)
log_link_error_errno(link, r, "Could not set bridge vlan: %m");
diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c
index a5085d2b19..12b0fe972f 100644
--- a/src/network/networkd-netdev-bridge.c
+++ b/src/network/networkd-netdev-bridge.c
@@ -108,6 +108,12 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m");
}
+ if (b->stp >= 0) {
+ r = sd_netlink_message_append_u32(req, IFLA_BR_STP_STATE, b->stp);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_STP_STATE attribute: %m");
+ }
+
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
@@ -135,6 +141,7 @@ static void bridge_init(NetDev *n) {
b->mcast_querier = -1;
b->mcast_snooping = -1;
b->vlan_filtering = -1;
+ b->stp = -1;
}
const NetDevVTable bridge_vtable = {
diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h
index a637aea0a3..4ce0fbb6f9 100644
--- a/src/network/networkd-netdev-bridge.h
+++ b/src/network/networkd-netdev-bridge.h
@@ -27,6 +27,7 @@ typedef struct Bridge {
int mcast_querier;
int mcast_snooping;
int vlan_filtering;
+ int stp;
usec_t forward_delay;
usec_t hello_time;
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index 9d69f61376..a1ca1a3d4e 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -106,4 +106,5 @@ Bridge.ForwardDelaySec, config_parse_sec, 0,
Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier)
Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping)
Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering)
+Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp)
VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table_id)
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 19adac66b8..b96f0b7210 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -115,7 +115,7 @@ Bridge.AllowPortToBeRoot, config_parse_bool,
Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
-BridgeVLAN.PVID, config_parse_vlanid, 0, offsetof(Network, pvid)
+BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0
BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
/* backwards compatibility: do not add new entries to this section */
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 7c0bdc1e4a..5460eb4d1c 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -151,6 +151,7 @@ struct Network {
bool unicast_flood;
unsigned cost;
+ bool use_br_vlan;
uint16_t pvid;
uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN];
uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN];
diff --git a/src/run/run.c b/src/run/run.c
index 58fa49a4d1..1917ffd857 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -257,11 +257,9 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_NICE:
- r = safe_atoi(optarg, &arg_nice);
- if (r < 0 || arg_nice < PRIO_MIN || arg_nice >= PRIO_MAX) {
- log_error("Failed to parse nice value");
- return -EINVAL;
- }
+ r = parse_nice(optarg, &arg_nice);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse nice value: %s", optarg);
arg_nice_set = true;
break;
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 589f9d46e9..c3a5233532 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -366,15 +366,13 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
}
} else if (streq(field, "Nice")) {
- int32_t i;
+ int n;
- r = safe_atoi32(eq, &i);
- if (r < 0) {
- log_error("Failed to parse %s value %s.", field, eq);
- return -EINVAL;
- }
+ r = parse_nice(eq, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse nice value: %s", eq);
- r = sd_bus_message_append(m, "v", "i", i);
+ r = sd_bus_message_append(m, "v", "i", (int32_t) n);
} else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
const char *p;
diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c
index 097c464229..d08014100b 100644
--- a/src/test/test-parse-util.c
+++ b/src/test/test-parse-util.c
@@ -498,6 +498,34 @@ static void test_parse_percent_unbounded(void) {
assert_se(parse_percent_unbounded("400%") == 400);
}
+static void test_parse_nice(void) {
+ int n;
+
+ assert_se(parse_nice("0", &n) >= 0 && n == 0);
+ assert_se(parse_nice("+0", &n) >= 0 && n == 0);
+ assert_se(parse_nice("-1", &n) >= 0 && n == -1);
+ assert_se(parse_nice("-2", &n) >= 0 && n == -2);
+ assert_se(parse_nice("1", &n) >= 0 && n == 1);
+ assert_se(parse_nice("2", &n) >= 0 && n == 2);
+ assert_se(parse_nice("+1", &n) >= 0 && n == 1);
+ assert_se(parse_nice("+2", &n) >= 0 && n == 2);
+ assert_se(parse_nice("-20", &n) >= 0 && n == -20);
+ assert_se(parse_nice("19", &n) >= 0 && n == 19);
+ assert_se(parse_nice("+19", &n) >= 0 && n == 19);
+
+
+ assert_se(parse_nice("", &n) == -EINVAL);
+ assert_se(parse_nice("-", &n) == -EINVAL);
+ assert_se(parse_nice("+", &n) == -EINVAL);
+ assert_se(parse_nice("xx", &n) == -EINVAL);
+ assert_se(parse_nice("-50", &n) == -ERANGE);
+ assert_se(parse_nice("50", &n) == -ERANGE);
+ assert_se(parse_nice("+50", &n) == -ERANGE);
+ assert_se(parse_nice("-21", &n) == -ERANGE);
+ assert_se(parse_nice("20", &n) == -ERANGE);
+ assert_se(parse_nice("+20", &n) == -ERANGE);
+}
+
int main(int argc, char *argv[]) {
log_parse_environment();
log_open();
@@ -513,6 +541,7 @@ int main(int argc, char *argv[]) {
test_safe_atod();
test_parse_percent();
test_parse_percent_unbounded();
+ test_parse_nice();
return 0;
}