summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-01-13 20:07:13 +0100
committerLennart Poettering <lennart@poettering.net>2015-01-13 20:17:07 +0100
commit769d324c99aab129148bd25f5f663ef441287d86 (patch)
treee6d3335e4b7e59f47a248e64e17c507536ce223c /src
parentdb9fd84944807ebea04363dada761613360fa6f9 (diff)
networkd: make IP forwarding for IPv4 and IPv6 individually configurable
Diffstat (limited to 'src')
-rw-r--r--src/network/networkd-link.c38
-rw-r--r--src/network/networkd-manager.c2
-rw-r--r--src/network/networkd-network-gperf.gperf2
-rw-r--r--src/network/networkd-network.c6
-rw-r--r--src/network/networkd.h13
-rw-r--r--src/shared/conf-parser.c6
-rw-r--r--src/shared/util.h4
7 files changed, 54 insertions, 17 deletions
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 1e2596749f..e4800a10de 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -88,14 +88,24 @@ static bool link_lldp_enabled(Link *link) {
return link->network->lldp;
}
-static bool link_ip_forward_enabled(Link *link) {
+static bool link_ipv4_forward_enabled(Link *link) {
if (link->flags & IFF_LOOPBACK)
return false;
if (!link->network)
return false;
- return link->network->ip_forward;
+ return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV4, ADDRESS_FAMILY_YES);
+}
+
+static bool link_ipv6_forward_enabled(Link *link) {
+ if (link->flags & IFF_LOOPBACK)
+ return false;
+
+ if (!link->network)
+ return false;
+
+ return IN_SET(link->network->ip_forward, ADDRESS_FAMILY_IPV6, ADDRESS_FAMILY_YES);
}
#define FLAG_STRING(string, flag, old, new) \
@@ -1225,14 +1235,26 @@ static int link_enter_join_netdev(Link *link) {
return 0;
}
-static int link_set_ip_forward(Link *link) {
+static int link_set_ipv4_forward(Link *link) {
const char *p = NULL;
int r;
p = strappenda("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding");
- r = write_string_file_no_create(p, link_ip_forward_enabled(link) ? "1" : "0");
+ r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link)));
if (r < 0)
- log_link_warning_errno(link, r, "Cannot configure IP forwarding for interface: %m");
+ log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface: %m");
+
+ return 0;
+}
+
+static int link_set_ipv6_forward(Link *link) {
+ const char *p = NULL;
+ int r;
+
+ p = strappenda("/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)
+ log_link_warning_errno(link, r, "Cannot configure IPv6 forwarding for interface: %m");
return 0;
}
@@ -1248,7 +1270,11 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
- r = link_set_ip_forward(link);
+ r = link_set_ipv4_forward(link);
+ if (r < 0)
+ return r;
+
+ r = link_set_ipv6_forward(link);
if (r < 0)
return r;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 42b51137ef..4c9043486a 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -686,3 +686,5 @@ AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
return _ADDRESS_FAMILY_BOOLEAN_INVALID;
}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 3eb37b4d24..5f2f741966 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -44,7 +44,7 @@ Network.Domains, config_parse_domains, 0,
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr)
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
-Network.IPForward, config_parse_bool, 0, offsetof(Network, ip_forward)
+Network.IPForward, config_parse_address_family_boolean,0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Address.Address, config_parse_address, 0, 0
Address.Peer, config_parse_address, 0, 0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 98f199ad72..34a06d3f34 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -111,7 +111,7 @@ static int network_load_one(Manager *manager, const char *filename) {
/* IPMasquerade=yes implies IPForward=yes */
if (network->ip_masquerade)
- network->ip_forward = true;
+ network->ip_forward |= ADDRESS_FAMILY_IPV4;
LIST_PREPEND(networks, manager->networks, network);
@@ -489,6 +489,10 @@ int config_parse_dhcp(
assert(rvalue);
assert(data);
+ /* Note that this is mostly like
+ * config_parse_address_family_boolean(), except that it
+ * understands some old names for the enum values */
+
s = address_family_boolean_from_string(rvalue);
if (s < 0) {
diff --git a/src/network/networkd.h b/src/network/networkd.h
index ea4547b940..719a75b8b7 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -55,10 +55,11 @@ typedef struct AddressPool AddressPool;
typedef struct FdbEntry FdbEntry;
typedef enum AddressFamilyBoolean {
- ADDRESS_FAMILY_NO,
- ADDRESS_FAMILY_YES,
- ADDRESS_FAMILY_IPV4,
- ADDRESS_FAMILY_IPV6,
+ /* This is a bitmask, though it usually doesn't feel that way! */
+ ADDRESS_FAMILY_NO = 0,
+ ADDRESS_FAMILY_IPV4 = 1,
+ ADDRESS_FAMILY_IPV6 = 2,
+ ADDRESS_FAMILY_YES = 3,
_ADDRESS_FAMILY_BOOLEAN_MAX,
_ADDRESS_FAMILY_BOOLEAN_INVALID = -1,
} AddressFamilyBoolean;
@@ -120,8 +121,8 @@ struct Network {
unsigned cost;
+ AddressFamilyBoolean ip_forward;
bool ip_masquerade;
- bool ip_forward;
struct ether_addr *mac;
unsigned mtu;
@@ -391,3 +392,5 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union
const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
+
+int config_parse_address_family_boolean(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/shared/conf-parser.c b/src/shared/conf-parser.c
index a1a94da928..0b1af6c577 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -823,8 +823,7 @@ int config_parse_log_facility(
x = log_facility_unshifted_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse log facility, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log facility, ignoring: %s", rvalue);
return 0;
}
@@ -855,8 +854,7 @@ int config_parse_log_level(
x = log_level_from_string(rvalue);
if (x < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Failed to parse log level, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse log level, ignoring: %s", rvalue);
return 0;
}
diff --git a/src/shared/util.h b/src/shared/util.h
index b337249faa..850019ab9d 100644
--- a/src/shared/util.h
+++ b/src/shared/util.h
@@ -143,6 +143,10 @@ static inline const char* true_false(bool b) {
return b ? "true" : "false";
}
+static inline const char* one_zero(bool b) {
+ return b ? "1" : "0";
+}
+
static inline const char* strempty(const char *s) {
return s ? s : "";
}