packets on the network
interface will be forwarded to
other interfaces according to
- the routing table. Takes a
- boolean
- argument.</para></listitem>
+ the routing table. Takes
+ either a boolean argument, or
+ the values
+ <literal>ipv4</literal> or
+ <literal>ipv6</literal>, which
+ only enables IP forwarding for
+ the specified address
+ family.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>IPMasquerade=</varname></term>
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) \
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;
}
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;
return _ADDRESS_FAMILY_BOOLEAN_INVALID;
}
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
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
/* 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);
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) {
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;
unsigned cost;
+ AddressFamilyBoolean ip_forward;
bool ip_masquerade;
- bool ip_forward;
struct ether_addr *mac;
unsigned mtu;
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);
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;
}
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;
}
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 : "";
}