From: Lou Berger Date: Sun, 17 Jun 2018 18:55:01 +0000 (-0400) Subject: lib: don't open vrf specific socket when tcp|udp_l3mdev_accept != 0 X-Git-Tag: frr-6.1-dev~210^2~3 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=9dff11329085774e718c239f3f2e2f7dcc1e5381;p=matthieu%2Ffrr.git lib: don't open vrf specific socket when tcp|udp_l3mdev_accept != 0 Signed-off-by: Lou Berger --- diff --git a/lib/vrf.c b/lib/vrf.c index 797b25d01d..643ad29cf8 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -121,10 +121,10 @@ int vrf_switch_to_netns(vrf_id_t vrf_id) /* VRF is default VRF. silently ignore */ if (!vrf || vrf->vrf_id == VRF_DEFAULT) - return 0; + return 1; /* 1 = default */ /* VRF has no NETNS backend. silently ignore */ if (vrf->data.l.netns_name[0] == '\0') - return 0; + return 2; /* 2 = no netns */ name = ns_netns_pathname(NULL, vrf->data.l.netns_name); if (debug_vrf) zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id); @@ -505,6 +505,35 @@ void vrf_terminate(void) } } +static int vrf_default_accepts_vrf(int type) +{ + const char *fname = NULL; + char buf[32] = {0x0}; + int ret = 0; + FILE *fd = NULL; + + /* + * TCP & UDP services running in the default VRF context (ie., not bound + * to any VRF device) can work across all VRF domains by enabling the + * tcp_l3mdev_accept and udp_l3mdev_accept sysctl options: + * sysctl -w net.ipv4.tcp_l3mdev_accept=1 + * sysctl -w net.ipv4.udp_l3mdev_accept=1 + */ + if (type == SOCK_STREAM) + fname = "/proc/sys/net/ipv4/tcp_l3mdev_accept"; + else if (type == SOCK_DGRAM) + fname = "/proc/sys/net/ipv4/udp_l3mdev_accept"; + else + return ret; + fd = fopen(fname, "r"); + if (fd == NULL) + return ret; + fgets(buf, 32, fd); + ret = atoi(buf); + fclose(fd); + return ret; +} + /* Create a socket for the VRF. */ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, char *interfacename) @@ -515,6 +544,12 @@ int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, if (ret < 0) zlog_err("%s: Can't switch to VRF %u (%s)", __func__, vrf_id, safe_strerror(errno)); + if (ret > 0 && interfacename && vrf_default_accepts_vrf(type)) { + zlog_err("VRF socket not used since net.ipv4.%s_l3mdev_accept != 0", + (type == SOCK_STREAM ? "tcp" : "udp")); + errno = EEXIST; /* not sure if this is the best error... */ + return -2; + } ret = socket(domain, type, protocol); save_errno = errno; ret2 = vrf_switchback_to_initial();