summaryrefslogtreecommitdiff
path: root/src/network/networkd-address.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-01-13 13:47:08 +0100
committerLennart Poettering <lennart@poettering.net>2015-01-13 13:55:15 +0100
commit5a8bcb674f71a20e95df55319b34c556638378ce (patch)
treedb1de9b03cb9bf4c017a0f620cf9d310c9de6098 /src/network/networkd-address.c
parent76917807eb50ccde58901e8bec7ed3d408d1cc22 (diff)
networkd: add minimal IP forwarding and masquerading support to .network files
This adds two new settings to networkd's .network files: IPForwarding=yes and IPMasquerade=yes. The former controls the "forwarding" sysctl setting of the interface, thus controlling whether IP forwarding shall be enabled on the specific interface. The latter controls whether a firewall rule shall be installed that exposes traffic coming from the interface as coming from the local host to all other interfaces. This also enables both options by default for container network interfaces, thus making "systemd-nspawn --network-veth" have network connectivity out of the box.
Diffstat (limited to 'src/network/networkd-address.c')
-rw-r--r--src/network/networkd-address.c62
1 files changed, 57 insertions, 5 deletions
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index b28c2e08f2..b4eb91ebb6 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -21,13 +21,13 @@
#include <net/if.h>
-#include "networkd.h"
-#include "networkd-link.h"
-
#include "utf8.h"
#include "util.h"
#include "conf-parser.h"
+#include "fw-util.h"
#include "network-internal.h"
+#include "networkd.h"
+#include "networkd-link.h"
static void address_init(Address *address) {
assert(address);
@@ -103,6 +103,54 @@ void address_free(Address *address) {
free(address);
}
+int address_establish(Address *address, Link *link) {
+ bool masq;
+ int r;
+
+ assert(address);
+ assert(link);
+
+ masq = link->network &&
+ link->network->ip_masquerade &&
+ address->family == AF_INET &&
+ address->scope < RT_SCOPE_LINK;
+
+ /* Add firewall entry if this is requested */
+ if (address->ip_forward_done != masq) {
+ union in_addr_union masked = address->in_addr;
+ in_addr_mask(address->family, &masked, address->prefixlen);
+
+ r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not enable IP masquerading: %m");
+
+ address->ip_forward_done = masq;
+ }
+
+ return 0;
+}
+
+int address_release(Address *address, Link *link) {
+ int r;
+
+ assert(address);
+ assert(link);
+
+ /* Remove masquerading firewall entry if it was added */
+ if (address->ip_forward_done) {
+ union in_addr_union masked = address->in_addr;
+ in_addr_mask(address->family, &masked, address->prefixlen);
+
+ r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Failed to disable IP masquerading: %m");
+
+ address->ip_forward_done = false;
+ }
+
+ return 0;
+}
+
int address_drop(Address *address, Link *link,
sd_rtnl_message_handler_t callback) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
@@ -115,6 +163,8 @@ int address_drop(Address *address, Link *link,
assert(link->manager);
assert(link->manager->rtnl);
+ address_release(address, link);
+
r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
link->ifindex, address->family);
if (r < 0)
@@ -333,6 +383,8 @@ int address_configure(Address *address, Link *link,
link_ref(link);
+ address_establish(address, link);
+
return 0;
}
@@ -549,8 +601,7 @@ bool address_equal(Address *a1, Address *a2) {
return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
}
- case AF_INET6:
- {
+ case AF_INET6: {
uint64_t *b1, *b2;
b1 = (uint64_t*)&a1->in_addr.in6;
@@ -558,6 +609,7 @@ bool address_equal(Address *a1, Address *a2) {
return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
}
+
default:
assert_not_reached("Invalid address family");
}