summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-07-06 13:38:47 +0200
committerLennart Poettering <lennart@poettering.net>2015-07-06 13:41:51 +0200
commit15dee3f07c646fd345b0aa30c6566071b3365db7 (patch)
treedf46683e0b92a473722be313f4ab77f0fb00332e
parent1361205099406d2a19d64547448638a6b665af81 (diff)
downloadsystemd-15dee3f07c646fd345b0aa30c6566071b3365db7.tar.gz
networkd: be more defensive when writing to ipv4/ipv6 forwarding settings
1) never bother with setting the flag for loopback devices 2) if we fail to write the flag due to EROFS (which is likely to happen in containers where /proc/sys is read-only) or any other error, check if the flag already has the right value. If so, don't complain. Closes #469
-rw-r--r--src/basic/fileio.c11
-rw-r--r--src/basic/fileio.h2
-rw-r--r--src/network/networkd-link.c32
3 files changed, 39 insertions, 6 deletions
diff --git a/src/basic/fileio.c b/src/basic/fileio.c
index ff6b1a7ed7..00fb6f8b5c 100644
--- a/src/basic/fileio.c
+++ b/src/basic/fileio.c
@@ -134,6 +134,17 @@ int read_one_line_file(const char *fn, char **line) {
return 0;
}
+int verify_one_line_file(const char *fn, const char *line) {
+ _cleanup_free_ char *value = NULL;
+ int r;
+
+ r = read_one_line_file(fn, &value);
+ if (r < 0)
+ return r;
+
+ return streq(value, line);
+}
+
int read_full_stream(FILE *f, char **contents, size_t *size) {
size_t n, l;
_cleanup_free_ char *buf = NULL;
diff --git a/src/basic/fileio.h b/src/basic/fileio.h
index 5ae51c1e28..91d4a0d2d5 100644
--- a/src/basic/fileio.h
+++ b/src/basic/fileio.h
@@ -34,6 +34,8 @@ int read_one_line_file(const char *fn, char **line);
int read_full_file(const char *fn, char **contents, size_t *size);
int read_full_stream(FILE *f, char **contents, size_t *size);
+int verify_one_line_file(const char *fn, const char *line);
+
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(FILE *f, const char *fname, const char *separator, char ***l);
int load_env_file_pairs(FILE *f, const char *fname, const char *separator, char ***l);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index f67a19e50b..eb07e12773 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1486,35 +1486,55 @@ static int link_enter_join_netdev(Link *link) {
}
static int link_set_ipv4_forward(Link *link) {
- const char *p = NULL;
+ const char *p = NULL, *v;
int r;
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
return 0;
p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
- r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link)));
- if (r < 0)
+ v = one_zero(link_ipv4_forward_enabled(link));
+
+ r = write_string_file_no_create(p, v);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, v) > 0)
+ return 0;
+
log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname);
+ }
return 0;
}
static int link_set_ipv6_forward(Link *link) {
- const char *p = NULL;
+ const char *p = NULL, *v = NULL;
int r;
/* Make this a NOP if IPv6 is not available */
if (!socket_ipv6_is_supported())
return 0;
+ if (link->flags & IFF_LOOPBACK)
+ return 0;
+
if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID)
return 0;
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding");
- r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link)));
- if (r < 0)
+ v = one_zero(link_ipv6_forward_enabled(link));
+
+ r = write_string_file_no_create(p, v);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, v) > 0)
+ return 0;
+
log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
+ }
return 0;
}