aboutsummaryrefslogtreecommitdiffstats
path: root/src/vppinfra
diff options
context:
space:
mode:
Diffstat (limited to 'src/vppinfra')
-rw-r--r--src/vppinfra/CMakeLists.txt1
-rw-r--r--src/vppinfra/linux/netns.c55
-rw-r--r--src/vppinfra/linux/netns.h32
-rw-r--r--src/vppinfra/socket.c53
-rw-r--r--src/vppinfra/socket.h2
5 files changed, 140 insertions, 3 deletions
diff --git a/src/vppinfra/CMakeLists.txt b/src/vppinfra/CMakeLists.txt
index 728072cec3b..c682d70f6f1 100644
--- a/src/vppinfra/CMakeLists.txt
+++ b/src/vppinfra/CMakeLists.txt
@@ -204,6 +204,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
elf_clib.c
linux/mem.c
linux/sysfs.c
+ linux/netns.c
)
endif()
diff --git a/src/vppinfra/linux/netns.c b/src/vppinfra/linux/netns.c
new file mode 100644
index 00000000000..2bd62bd7d92
--- /dev/null
+++ b/src/vppinfra/linux/netns.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <sched.h>
+
+#include <vppinfra/format.h>
+
+__clib_export int
+clib_netns_open (u8 *netns_u8)
+{
+ char *netns = (char *) netns_u8;
+ u8 *s = 0;
+ int fd;
+
+ if ((NULL) == netns)
+ s = format (0, "/proc/self/ns/net");
+ else if (strncmp (netns, "pid:", 4) == 0)
+ s = format (0, "/proc/%u/ns/net%c", atoi (netns + 4), 0);
+ else if (netns[0] == '/')
+ s = format (0, "%s%c", netns, 0);
+ else
+ s = format (0, "/var/run/netns/%s%c", netns, 0);
+
+ fd = open ((char *) s, O_RDONLY);
+ vec_free (s);
+ return fd;
+}
+
+__clib_export int
+clib_setns (int nfd)
+{
+ return setns (nfd, CLONE_NEWNET);
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vppinfra/linux/netns.h b/src/vppinfra/linux/netns.h
new file mode 100644
index 00000000000..5a094607953
--- /dev/null
+++ b/src/vppinfra/linux/netns.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef included_vppinfra_netns_h
+#define included_vppinfra_netns_h
+
+#include <vppinfra/clib.h>
+
+int clib_netns_open (u8 *netns);
+int clib_setns (int nfd);
+
+#endif /* included_vppinfra_netns_h */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vppinfra/socket.c b/src/vppinfra/socket.c
index d8427852400..26427d98fa1 100644
--- a/src/vppinfra/socket.c
+++ b/src/vppinfra/socket.c
@@ -52,6 +52,7 @@
#include <vppinfra/mem.h>
#include <vppinfra/vec.h>
#include <vppinfra/socket.h>
+#include <vppinfra/linux/netns.h>
#include <vppinfra/format.h>
#include <vppinfra/error.h>
@@ -113,6 +114,18 @@ socket_config (char *config,
*addr_len = sizeof (su[0]);
}
+ /* Treat everything that starts with @ as an abstract socket. */
+ else if (config[0] == '@')
+ {
+ struct sockaddr_un *su = addr;
+ su->sun_family = PF_LOCAL;
+ clib_memcpy (&su->sun_path, config,
+ clib_min (sizeof (su->sun_path), 1 + strlen (config)));
+
+ *addr_len = sizeof (su->sun_family) + strlen (config);
+ su->sun_path[0] = '\0';
+ }
+
/* Hostname or hostname:port or port. */
else
{
@@ -440,7 +453,8 @@ clib_socket_init (clib_socket_t * s)
need_bind = 0;
}
}
- if (addr.sa.sa_family == PF_LOCAL)
+ if (addr.sa.sa_family == PF_LOCAL &&
+ ((struct sockaddr_un *) &addr)->sun_path[0] != 0)
unlink (((struct sockaddr_un *) &addr)->sun_path);
/* Make address available for multiple users. */
@@ -477,8 +491,9 @@ clib_socket_init (clib_socket_t * s)
s->fd, s->config);
goto done;
}
- if (addr.sa.sa_family == PF_LOCAL
- && s->flags & CLIB_SOCKET_F_ALLOW_GROUP_WRITE)
+ if (addr.sa.sa_family == PF_LOCAL &&
+ s->flags & CLIB_SOCKET_F_ALLOW_GROUP_WRITE &&
+ ((struct sockaddr_un *) &addr)->sun_path[0] != 0)
{
struct stat st = { 0 };
if (stat (((struct sockaddr_un *) &addr)->sun_path, &st) < 0)
@@ -539,6 +554,38 @@ done:
}
__clib_export clib_error_t *
+clib_socket_init_netns (clib_socket_t *s, u8 *namespace)
+{
+ if (namespace == NULL || namespace[0] == 0)
+ return clib_socket_init (s);
+
+ clib_error_t *error;
+ int old_netns_fd, nfd;
+
+ old_netns_fd = clib_netns_open (NULL /* self */);
+ if ((nfd = clib_netns_open (namespace)) == -1)
+ {
+ error = clib_error_return_unix (0, "clib_netns_open '%s'", namespace);
+ goto done;
+ }
+
+ if (clib_setns (nfd) == -1)
+ {
+ error = clib_error_return_unix (0, "setns '%s'", namespace);
+ goto done;
+ }
+
+ error = clib_socket_init (s);
+
+done:
+ if (clib_setns (old_netns_fd) == -1)
+ clib_warning ("Cannot set old ns");
+ close (old_netns_fd);
+
+ return error;
+}
+
+__clib_export clib_error_t *
clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
{
clib_error_t *err = 0;
diff --git a/src/vppinfra/socket.h b/src/vppinfra/socket.h
index 78a56fee53e..fa5ef1efced 100644
--- a/src/vppinfra/socket.h
+++ b/src/vppinfra/socket.h
@@ -93,6 +93,8 @@ typedef struct _socket_t
from IPPORT_USERRESERVED (5000). */
clib_error_t *clib_socket_init (clib_socket_t * socket);
+clib_error_t *clib_socket_init_netns (clib_socket_t *socket, u8 *namespace);
+
clib_error_t *clib_socket_accept (clib_socket_t * server,
clib_socket_t * client);