blob: a22f1a5c456106f01a07a42b889fccc7356e41ba [file] [log] [blame]
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01001#define _GNU_SOURCE
2
3#include <common/namespace.h>
4#include <common/compiler.h>
5#include <common/hash.h>
6#include <common/errors.h>
7#include <proto/log.h>
8#include <types/global.h>
9
10#include <sched.h>
11#include <stdio.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <sys/types.h>
15#include <unistd.h>
16#include <sys/socket.h>
17
18#include <string.h>
19#ifdef CONFIG_HAP_NS
20
21/* Opens the namespace <ns_name> and returns the FD or -1 in case of error
22 * (check errno).
23 */
24static int open_named_namespace(const char *ns_name)
25{
26 if (chunk_printf(&trash, "/var/run/netns/%s", ns_name) < 0)
27 return -1;
28 return open(trash.str, O_RDONLY);
29}
30
31static int default_namespace = -1;
32
33static int init_default_namespace()
34{
35 if (chunk_printf(&trash, "/proc/%d/ns/net", getpid()) < 0)
36 return -1;
37 default_namespace = open(trash.str, O_RDONLY);
38 return default_namespace;
39}
40
41static struct eb_root namespace_tree_root = EB_ROOT;
42
43int netns_init(void)
44{
45 int err_code = 0;
46
47 /* if no namespaces have been defined in the config then
48 * there is no point in trying to initialize anything:
49 * my_socketat() will never be called with a valid namespace
50 * structure and thus switching back to the default namespace
51 * is not needed either */
52 if (!eb_is_empty(&namespace_tree_root)) {
53 if (init_default_namespace() < 0) {
54 Alert("Failed to open the default namespace.\n");
55 err_code |= ERR_ALERT | ERR_FATAL;
56 }
57 }
58
59 return err_code;
60}
61
62struct netns_entry* netns_store_insert(const char *ns_name)
63{
64 struct netns_entry *entry = NULL;
65 int fd = open_named_namespace(ns_name);
66 if (fd == -1)
67 goto out;
68
69 entry = (struct netns_entry *)calloc(1, sizeof(struct netns_entry));
70 if (!entry)
71 goto out;
72 entry->fd = fd;
73 entry->node.key = strdup(ns_name);
74 entry->name_len = strlen(ns_name);
75 ebis_insert(&namespace_tree_root, &entry->node);
76out:
77 return entry;
78}
79
80const struct netns_entry* netns_store_lookup(const char *ns_name, size_t ns_name_len)
81{
82 struct ebpt_node *node;
83
84 node = ebis_lookup_len(&namespace_tree_root, ns_name, ns_name_len);
85 if (node)
86 return ebpt_entry(node, struct netns_entry, node);
87 else
88 return NULL;
89}
90#endif
91
92/* Opens a socket in the namespace described by <ns> with the parameters <domain>,
93 * <type> and <protocol> and returns the FD or -1 in case of error (check errno).
94 */
95int my_socketat(const struct netns_entry *ns, int domain, int type, int protocol)
96{
97 int sock;
98
99#ifdef CONFIG_HAP_NS
100 if (default_namespace < 0 ||
101 (ns && setns(ns->fd, CLONE_NEWNET) == -1))
102 return -1;
103#endif
104 sock = socket(domain, type, protocol);
105
106#ifdef CONFIG_HAP_NS
107 if (ns && setns(default_namespace, CLONE_NEWNET) == -1) {
108 close(sock);
109 return -1;
110 }
111#endif
112
113 return sock;
114}