aboutgitcodebugslistschat
diff options
context:
space:
mode:
-rw-r--r--conf.c15
-rw-r--r--netlink.c92
-rw-r--r--netlink.h28
-rw-r--r--pasta.c46
4 files changed, 105 insertions, 76 deletions
diff --git a/conf.c b/conf.c
index e538b08..7286f92 100644
--- a/conf.c
+++ b/conf.c
@@ -641,7 +641,7 @@ static unsigned int conf_ip4(unsigned int ifi,
struct ip4_ctx *ip4, unsigned char *mac)
{
if (!ifi)
- ifi = nl_get_ext_if(AF_INET);
+ ifi = nl_get_ext_if(nl_sock, AF_INET);
if (!ifi) {
warn("No external routable interface for IPv4");
@@ -649,10 +649,11 @@ static unsigned int conf_ip4(unsigned int ifi,
}
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->gw))
- nl_route_get_def(ifi, AF_INET, &ip4->gw);
+ nl_route_get_def(nl_sock, ifi, AF_INET, &ip4->gw);
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr))
- nl_addr_get(ifi, AF_INET, &ip4->addr, &ip4->prefix_len, NULL);
+ nl_addr_get(nl_sock, ifi, AF_INET,
+ &ip4->addr, &ip4->prefix_len, NULL);
if (!ip4->prefix_len) {
in_addr_t addr = ntohl(ip4->addr.s_addr);
@@ -669,7 +670,7 @@ static unsigned int conf_ip4(unsigned int ifi,
memcpy(&ip4->addr_seen, &ip4->addr, sizeof(ip4->addr_seen));
if (MAC_IS_ZERO(mac))
- nl_link_get_mac(0, ifi, mac);
+ nl_link_get_mac(nl_sock, ifi, mac);
if (IN4_IS_ADDR_UNSPECIFIED(&ip4->addr) ||
MAC_IS_ZERO(mac))
@@ -692,7 +693,7 @@ static unsigned int conf_ip6(unsigned int ifi,
int prefix_len = 0;
if (!ifi)
- ifi = nl_get_ext_if(AF_INET6);
+ ifi = nl_get_ext_if(nl_sock, AF_INET6);
if (!ifi) {
warn("No external routable interface for IPv6");
@@ -700,9 +701,9 @@ static unsigned int conf_ip6(unsigned int ifi,
}
if (IN6_IS_ADDR_UNSPECIFIED(&ip6->gw))
- nl_route_get_def(ifi, AF_INET6, &ip6->gw);
+ nl_route_get_def(nl_sock, ifi, AF_INET6, &ip6->gw);
- nl_addr_get(ifi, AF_INET6,
+ nl_addr_get(nl_sock, ifi, AF_INET6,
IN6_IS_ADDR_UNSPECIFIED(&ip6->addr) ? &ip6->addr : NULL,
&prefix_len, &ip6->addr_ll);
diff --git a/netlink.c b/netlink.c
index 47f2ba1..498c687 100644
--- a/netlink.c
+++ b/netlink.c
@@ -38,8 +38,8 @@
#define NLBUFSIZ (8192 * sizeof(struct nlmsghdr)) /* See netlink(7) */
/* Socket in init, in target namespace, sequence (just needs to be monotonic) */
-static int nl_sock = -1;
-static int nl_sock_ns = -1;
+int nl_sock = -1;
+int nl_sock_ns = -1;
static int nl_seq;
/**
@@ -98,17 +98,17 @@ fail:
/**
* nl_req() - Send netlink request and read response
- * @ns: Use netlink socket in namespace
+ * @s: Netlink socket
* @buf: Buffer for response (at least NLBUFSIZ long)
* @req: Request with netlink header
* @len: Request length
*
* Return: received length on success, negative error code on failure
*/
-static int nl_req(int ns, char *buf, const void *req, ssize_t len)
+static int nl_req(int s, char *buf, const void *req, ssize_t len)
{
- int s = ns ? nl_sock_ns : nl_sock, done = 0;
char flush[NLBUFSIZ];
+ int done = 0;
ssize_t n;
while (!done && (n = recv(s, flush, sizeof(flush), MSG_DONTWAIT)) > 0) {
@@ -133,12 +133,13 @@ static int nl_req(int ns, char *buf, const void *req, ssize_t len)
/**
* nl_get_ext_if() - Get interface index supporting IP version being probed
+ * @s: Netlink socket
* @af: Address family (AF_INET or AF_INET6) to look for connectivity
* for.
*
* Return: interface index, 0 if not found
*/
-unsigned int nl_get_ext_if(sa_family_t af)
+unsigned int nl_get_ext_if(int s, sa_family_t af)
{
struct { struct nlmsghdr nlh; struct rtmsg rtm; } req = {
.nlh.nlmsg_type = RTM_GETROUTE,
@@ -157,7 +158,7 @@ unsigned int nl_get_ext_if(sa_family_t af)
ssize_t n;
size_t na;
- if ((n = nl_req(0, buf, &req, sizeof(req))) < 0)
+ if ((n = nl_req(s, buf, &req, sizeof(req))) < 0)
return 0;
nh = (struct nlmsghdr *)buf;
@@ -186,11 +187,12 @@ unsigned int nl_get_ext_if(sa_family_t af)
/**
* nl_route_get_def() - Get default route for given interface and address family
+ * @s: Netlink socket
* @ifi: Interface index
* @af: Address family
* @gw: Default gateway to fill on NL_GET
*/
-void nl_route_get_def(unsigned int ifi, sa_family_t af, void *gw)
+void nl_route_get_def(int s, unsigned int ifi, sa_family_t af, void *gw)
{
struct req_t {
struct nlmsghdr nlh;
@@ -216,7 +218,7 @@ void nl_route_get_def(unsigned int ifi, sa_family_t af, void *gw)
char buf[NLBUFSIZ];
ssize_t n;
- if ((n = nl_req(0, buf, &req, req.nlh.nlmsg_len)) < 0)
+ if ((n = nl_req(s, buf, &req, req.nlh.nlmsg_len)) < 0)
return;
for (nh = (struct nlmsghdr *)buf;
@@ -245,11 +247,12 @@ void nl_route_get_def(unsigned int ifi, sa_family_t af, void *gw)
/**
* nl_route_set_def() - Set default route for given interface and address family
+ * @s: Netlink socket
* @ifi: Interface index in target namespace
* @af: Address family
* @gw: Default gateway to set
*/
-void nl_route_set_def(unsigned int ifi, sa_family_t af, void *gw)
+void nl_route_set_def(int s, unsigned int ifi, sa_family_t af, void *gw)
{
struct req_t {
struct nlmsghdr nlh;
@@ -314,16 +317,19 @@ void nl_route_set_def(unsigned int ifi, sa_family_t af, void *gw)
req.set.r4.rta_gw.rta_len = rta_len;
}
- nl_req(1, buf, &req, req.nlh.nlmsg_len);
+ nl_req(s, buf, &req, req.nlh.nlmsg_len);
}
/**
* nl_route_dup() - Copy routes for given interface and address family
- * @ifi: Interface index in outer network namespace
- * @ifi_ns: Interface index in target namespace for NL_SET, NL_DUP
+ * @s_src: Netlink socket in source namespace
+ * @ifi_src: Source interface index
+ * @s_dst: Netlink socket in destination namespace
+ * @ifi_dst: Interface index in destination namespace
* @af: Address family
*/
-void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
+void nl_route_dup(int s_src, unsigned int ifi_src,
+ int s_dst, unsigned int ifi_dst, sa_family_t af)
{
struct req_t {
struct nlmsghdr nlh;
@@ -343,7 +349,7 @@ void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
.rta.rta_type = RTA_OIF,
.rta.rta_len = RTA_LENGTH(sizeof(unsigned int)),
- .ifi = ifi,
+ .ifi = ifi_src,
};
char buf[NLBUFSIZ], resp[NLBUFSIZ];
unsigned dup_routes = 0;
@@ -351,7 +357,7 @@ void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
struct nlmsghdr *nh;
unsigned i;
- if ((n = nl_req(0, buf, &req, req.nlh.nlmsg_len)) < 0)
+ if ((n = nl_req(s_src, buf, &req, req.nlh.nlmsg_len)) < 0)
return;
nlmsgs_size = n;
@@ -376,7 +382,7 @@ void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
for (rta = RTM_RTA(rtm), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
rta = RTA_NEXT(rta, na)) {
if (rta->rta_type == RTA_OIF)
- *(unsigned int *)RTA_DATA(rta) = ifi_ns;
+ *(unsigned int *)RTA_DATA(rta) = ifi_dst;
}
}
@@ -389,19 +395,20 @@ void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
* avoids the need to calculate dependencies: let the kernel do that.
*/
for (i = 0; i < dup_routes; i++)
- nl_req(1, resp, nh, nlmsgs_size);
+ nl_req(s_dst, resp, nh, nlmsgs_size);
}
/**
* nl_addr_get() - Get IP address for given interface and address family
+ * @s: Netlink socket
* @ifi: Interface index in outer network namespace
* @af: Address family
* @addr: Global address to fill
* @prefix_len: Mask or prefix length, to fill (for IPv4)
* @addr_l: Link-scoped address to fill (for IPv6)
*/
-void nl_addr_get(unsigned int ifi, sa_family_t af, void *addr,
- int *prefix_len, void *addr_l)
+void nl_addr_get(int s, unsigned int ifi, sa_family_t af,
+ void *addr, int *prefix_len, void *addr_l)
{
struct req_t {
struct nlmsghdr nlh;
@@ -419,7 +426,7 @@ void nl_addr_get(unsigned int ifi, sa_family_t af, void *addr,
char buf[NLBUFSIZ];
ssize_t n;
- if ((n = nl_req(0, buf, &req, req.nlh.nlmsg_len)) < 0)
+ if ((n = nl_req(s, buf, &req, req.nlh.nlmsg_len)) < 0)
return;
for (nh = (struct nlmsghdr *)buf;
@@ -457,12 +464,14 @@ void nl_addr_get(unsigned int ifi, sa_family_t af, void *addr,
/**
* nl_add_set() - Set IP addresses for given interface and address family
+ * @s: Netlink socket
* @ifi: Interface index
* @af: Address family
* @addr: Global address to set
* @prefix_len: Mask or prefix length to set
*/
-void nl_addr_set(unsigned int ifi, sa_family_t af, void *addr, int prefix_len)
+void nl_addr_set(int s, unsigned int ifi, sa_family_t af,
+ void *addr, int prefix_len)
{
struct req_t {
struct nlmsghdr nlh;
@@ -523,16 +532,19 @@ void nl_addr_set(unsigned int ifi, sa_family_t af, void *addr, int prefix_len)
req.set.a4.rta_a.rta_type = IFA_ADDRESS;
}
- nl_req(1, buf, &req, req.nlh.nlmsg_len);
+ nl_req(s, buf, &req, req.nlh.nlmsg_len);
}
/**
* nl_addr_dup() - Copy IP addresses for given interface and address family
- * @ifi: Interface index in outer network namespace
- * @ifi_ns: Interface index in target namespace
+ * @s_src: Netlink socket in source network namespace
+ * @ifi_src: Interface index in source network namespace
+ * @s_dst: Netlink socket in destination network namespace
+ * @ifi_dst: Interface index in destination namespace
* @af: Address family
*/
-void nl_addr_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
+void nl_addr_dup(int s_src, unsigned int ifi_src,
+ int s_dst, unsigned int ifi_dst, sa_family_t af)
{
struct req_t {
struct nlmsghdr nlh;
@@ -544,14 +556,14 @@ void nl_addr_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
.nlh.nlmsg_seq = nl_seq++,
.ifa.ifa_family = af,
- .ifa.ifa_index = ifi,
+ .ifa.ifa_index = ifi_src,
.ifa.ifa_prefixlen = 0,
};
char buf[NLBUFSIZ], resp[NLBUFSIZ];
ssize_t n, nlmsgs_size;
struct nlmsghdr *nh;
- if ((n = nl_req(0, buf, &req, sizeof(req))) < 0)
+ if ((n = nl_req(s_src, buf, &req, sizeof(req))) < 0)
return;
nlmsgs_size = n;
@@ -573,12 +585,13 @@ void nl_addr_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
- if (ifa->ifa_scope == RT_SCOPE_LINK || ifa->ifa_index != ifi) {
+ if (ifa->ifa_scope == RT_SCOPE_LINK ||
+ ifa->ifa_index != ifi_src) {
ifa->ifa_family = AF_UNSPEC;
continue;
}
- ifa->ifa_index = ifi_ns;
+ ifa->ifa_index = ifi_dst;
for (rta = IFA_RTA(ifa), na = RTM_PAYLOAD(nh); RTA_OK(rta, na);
rta = RTA_NEXT(rta, na)) {
@@ -587,16 +600,16 @@ void nl_addr_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af)
}
}
- nl_req(1, resp, buf, nlmsgs_size);
+ nl_req(s_dst, resp, buf, nlmsgs_size);
}
/**
* nl_link_get_mac() - Get link MAC address
- * @ns: Use netlink socket in namespace
+ * @s: Netlink socket
* @ifi: Interface index
* @mac: Fill with current MAC address
*/
-void nl_link_get_mac(int ns, unsigned int ifi, void *mac)
+void nl_link_get_mac(int s, unsigned int ifi, void *mac)
{
struct req_t {
struct nlmsghdr nlh;
@@ -613,7 +626,7 @@ void nl_link_get_mac(int ns, unsigned int ifi, void *mac)
char buf[NLBUFSIZ];
ssize_t n;
- n = nl_req(ns, buf, &req, sizeof(req));
+ n = nl_req(s, buf, &req, sizeof(req));
if (n < 0)
return;
@@ -641,11 +654,12 @@ void nl_link_get_mac(int ns, unsigned int ifi, void *mac)
/**
* nl_link_set_mac() - Set link MAC address
+ * @s: Netlink socket
* @ns: Use netlink socket in namespace
* @ifi: Interface index
* @mac: MAC address to set
*/
-void nl_link_set_mac(int ns, unsigned int ifi, void *mac)
+void nl_link_set_mac(int s, unsigned int ifi, void *mac)
{
struct req_t {
struct nlmsghdr nlh;
@@ -666,16 +680,16 @@ void nl_link_set_mac(int ns, unsigned int ifi, void *mac)
memcpy(req.mac, mac, ETH_ALEN);
- nl_req(ns, buf, &req, sizeof(req));
+ nl_req(s, buf, &req, sizeof(req));
}
/**
* nl_link_up() - Bring link up
- * @ns: Use netlink socket in namespace
+ * @s: Netlink socket
* @ifi: Interface index
* @mtu: If non-zero, set interface MTU
*/
-void nl_link_up(int ns, unsigned int ifi, int mtu)
+void nl_link_up(int s, unsigned int ifi, int mtu)
{
struct req_t {
struct nlmsghdr nlh;
@@ -701,5 +715,5 @@ void nl_link_up(int ns, unsigned int ifi, int mtu)
/* Shorten request to drop MTU attribute */
req.nlh.nlmsg_len = offsetof(struct req_t, rta);
- nl_req(ns, buf, &req, req.nlh.nlmsg_len);
+ nl_req(s, buf, &req, req.nlh.nlmsg_len);
}
diff --git a/netlink.h b/netlink.h
index 36bbf9f..5ca17c6 100644
--- a/netlink.h
+++ b/netlink.h
@@ -6,17 +6,23 @@
#ifndef NETLINK_H
#define NETLINK_H
+extern int nl_sock;
+extern int nl_sock_ns;
+
void nl_sock_init(const struct ctx *c, bool ns);
-unsigned int nl_get_ext_if(sa_family_t af);
-void nl_route_get_def(unsigned int ifi, sa_family_t af, void *gw);
-void nl_route_set_def(unsigned int ifi, sa_family_t af, void *gw);
-void nl_route_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af);
-void nl_addr_get(unsigned int ifi, sa_family_t af, void *addr,
- int *prefix_len, void *addr_l);
-void nl_addr_set(unsigned int ifi, sa_family_t af, void *addr, int prefix_len);
-void nl_addr_dup(unsigned int ifi, unsigned int ifi_ns, sa_family_t af);
-void nl_link_get_mac(int ns, unsigned int ifi, void *mac);
-void nl_link_set_mac(int ns, unsigned int ifi, void *mac);
-void nl_link_up(int ns, unsigned int ifi, int mtu);
+unsigned int nl_get_ext_if(int s, sa_family_t af);
+void nl_route_get_def(int s, unsigned int ifi, sa_family_t af, void *gw);
+void nl_route_set_def(int s, unsigned int ifi, sa_family_t af, void *gw);
+void nl_route_dup(int s_src, unsigned int ifi_src,
+ int s_dst, unsigned int ifi_dst, sa_family_t af);
+void nl_addr_get(int s, unsigned int ifi, sa_family_t af,
+ void *addr, int *prefix_len, void *addr_l);
+void nl_addr_set(int s, unsigned int ifi, sa_family_t af,
+ void *addr, int prefix_len);
+void nl_addr_dup(int s_src, unsigned int ifi_src,
+ int s_dst, unsigned int ifi_dst, sa_family_t af);
+void nl_link_get_mac(int s, unsigned int ifi, void *mac);
+void nl_link_set_mac(int s, unsigned int ifi, void *mac);
+void nl_link_up(int s, unsigned int ifi, int mtu);
#endif /* NETLINK_H */
diff --git a/pasta.c b/pasta.c
index 52cfad7..36c63de 100644
--- a/pasta.c
+++ b/pasta.c
@@ -272,45 +272,53 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
*/
void pasta_ns_conf(struct ctx *c)
{
- nl_link_up(1, 1 /* lo */, 0);
+ nl_link_up(nl_sock_ns, 1 /* lo */, 0);
/* Get or set MAC in target namespace */
if (MAC_IS_ZERO(c->mac_guest))
- nl_link_get_mac(1, c->pasta_ifi, c->mac_guest);
+ nl_link_get_mac(nl_sock_ns, c->pasta_ifi, c->mac_guest);
else
- nl_link_set_mac(1, c->pasta_ifi, c->mac_guest);
+ nl_link_set_mac(nl_sock_ns, c->pasta_ifi, c->mac_guest);
if (c->pasta_conf_ns) {
- nl_link_up(1, c->pasta_ifi, c->mtu);
+ nl_link_up(nl_sock_ns, c->pasta_ifi, c->mtu);
if (c->ifi4) {
if (c->no_copy_addrs) {
- nl_addr_set(c->pasta_ifi, AF_INET,
+ nl_addr_set(nl_sock_ns, c->pasta_ifi, AF_INET,
&c->ip4.addr, c->ip4.prefix_len);
} else {
- nl_addr_dup(c->ifi4, c->pasta_ifi, AF_INET);
+ nl_addr_dup(nl_sock, c->ifi4,
+ nl_sock_ns, c->pasta_ifi, AF_INET);
}
- if (c->no_copy_routes)
- nl_route_set_def(c->pasta_ifi, AF_INET,
- &c->ip4.gw);
- else
- nl_route_dup(c->ifi4, c->pasta_ifi, AF_INET);
+ if (c->no_copy_routes) {
+ nl_route_set_def(nl_sock_ns, c->pasta_ifi,
+ AF_INET, &c->ip4.gw);
+ } else {
+ nl_route_dup(nl_sock, c->ifi4, nl_sock_ns,
+ c->pasta_ifi, AF_INET);
+ }
}
if (c->ifi6) {
if (c->no_copy_addrs) {
- nl_addr_set(c->pasta_ifi, AF_INET6,
- &c->ip6.addr, 64);
+ nl_addr_set(nl_sock_ns, c->pasta_ifi,
+ AF_INET6, &c->ip6.addr, 64);
} else {
- nl_addr_dup(c->ifi6, c->pasta_ifi, AF_INET6);
+ nl_addr_dup(nl_sock, c->ifi6,
+ nl_sock_ns, c->pasta_ifi,
+ AF_INET6);
}
- if (c->no_copy_routes)
- nl_route_set_def(c->pasta_ifi, AF_INET6,
- &c->ip6.gw);
- else
- nl_route_dup(c->ifi6, c->pasta_ifi, AF_INET6);
+ if (c->no_copy_routes) {
+ nl_route_set_def(nl_sock_ns, c->pasta_ifi,
+ AF_INET6, &c->ip6.gw);
+ } else {
+ nl_route_dup(nl_sock, c->ifi6,
+ nl_sock_ns, c->pasta_ifi,
+ AF_INET6);
+ }
}
}