netifd: vxlan: handle srcport range
authorJohannes Kimmel <fff@bareminimum.eu>
Fri, 4 Sep 2020 02:59:40 +0000 (04:59 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Sat, 12 Sep 2020 19:04:42 +0000 (21:04 +0200)
This adds adds the ability to set the source port range for vxlan
interfaces.

By default vxlans will use a random port within the ephermal range as
source ports for packets. This is done to aid scaleability within a
datacenter.

But with these defaults it's impossible to punch through NATs or
traverese most stateful firewalls easily. One solution is to fix the
srcport to the same as dstport.

If only srcportmin is specified, then srcportmax is set in a way that
outgoing packets will only use srcportmin.

If a range is to be specified, srcportmin and srcportmax have to be
specified. srcportmax is exclusive.

If only srcportmax is specified, the value is ignored and defaults are
used.

Signed-off-by: Johannes Kimmel <fff@bareminimum.eu>
system-linux.c
system.c
system.h

index c5583e079c9b9a3eaabd704bcfe3a959e07bc9bb..42f0de3bbe0ec6259d69a6454dd02f4506d1599f 100644 (file)
@@ -3184,6 +3184,32 @@ static int system_add_vxlan(const char *name, const unsigned int link, struct bl
        }
        nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port));
 
+       if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMIN])) {
+               struct ifla_vxlan_port_range srcports = {0,0};
+
+               uint32_t low = blobmsg_get_u32(cur);
+               if (low < 1 || low > 65535 - 1) {
+                       ret = -EINVAL;
+                       goto failure;
+               }
+
+               srcports.low = htons((uint16_t) low);
+               srcports.high = htons((uint16_t) (low+1));
+
+               if ((cur = tb_data[VXLAN_DATA_ATTR_SRCPORTMAX])) {
+                       uint32_t high = blobmsg_get_u32(cur);
+                       if (high < 1 || high > 65535) {
+                               ret = -EINVAL;
+                               goto failure;
+                       }
+
+                       if (high > low)
+                               srcports.high = htons((uint16_t) high);
+               }
+
+               nla_put(msg, IFLA_VXLAN_PORT_RANGE, sizeof(srcports), &srcports);
+       }
+
        if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) {
                bool rxcsum = blobmsg_get_bool(cur);
                nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum);
index bbdfef7706653f79c5116e4b8b73342029cfc496..4133e553461b390511fee4c201bb6c952a05ed61 100644 (file)
--- a/system.c
+++ b/system.c
@@ -38,6 +38,8 @@ static const struct blobmsg_policy vxlan_data_attrs[__VXLAN_DATA_ATTR_MAX] = {
        [VXLAN_DATA_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING },
        [VXLAN_DATA_ATTR_RXCSUM] = { .name = "rxcsum", .type = BLOBMSG_TYPE_BOOL },
        [VXLAN_DATA_ATTR_TXCSUM] = { .name = "txcsum", .type = BLOBMSG_TYPE_BOOL },
+       [VXLAN_DATA_ATTR_SRCPORTMIN] = { .name = "srcportmin", .type = BLOBMSG_TYPE_INT32 },
+       [VXLAN_DATA_ATTR_SRCPORTMAX] = { .name = "srcportmax", .type = BLOBMSG_TYPE_INT32 },
 };
 
 const struct uci_blob_param_list vxlan_data_attr_list = {
index 015987f285f2f81ce1ca753fcdee32c576ad6c57..bf9e1d76200e85aeb8756ddce87d902c3bc096a2 100644 (file)
--- a/system.h
+++ b/system.h
@@ -44,6 +44,8 @@ enum vxlan_data {
        VXLAN_DATA_ATTR_MACADDR,
        VXLAN_DATA_ATTR_RXCSUM,
        VXLAN_DATA_ATTR_TXCSUM,
+       VXLAN_DATA_ATTR_SRCPORTMIN,
+       VXLAN_DATA_ATTR_SRCPORTMAX,
        __VXLAN_DATA_ATTR_MAX
 };