networkd: make IP forwarding for IPv4 and IPv6 individually configurable
This commit is contained in:
parent
db9fd84944
commit
769d324c99
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 : "";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue