]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: don't open vrf specific socket when tcp|udp_l3mdev_accept != 0
authorLou Berger <lberger@labn.net>
Sun, 17 Jun 2018 18:55:01 +0000 (14:55 -0400)
committerLou Berger <lberger@labn.net>
Sat, 23 Jun 2018 20:37:40 +0000 (16:37 -0400)
Signed-off-by: Lou Berger <lberger@labn.net>
lib/vrf.c

index e1176d152603a742cd80260daf227583e127caed..a60112e07f13675fb24e76665c481c64174c1c40 100644 (file)
--- 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();