networkd: make IP forwarding for IPv4 and IPv6 individually configurable

This commit is contained in:
Lennart Poettering 2015-01-13 20:07:13 +01:00
parent db9fd84944
commit 769d324c99
8 changed files with 62 additions and 20 deletions

View File

@ -352,9 +352,14 @@
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>

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}

View File

@ -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 : "";
}