Skip to content

Commit 67ce5bf

Browse files
committed
WIP
Signed-off-by: Gianmarco De Gregori <gianmarco@mandelbit.com>
1 parent 2ea83c7 commit 67ce5bf

3 files changed

Lines changed: 172 additions & 29 deletions

File tree

src/openvpn/networking_sitnl.c

Lines changed: 150 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
_nest->rta_len = (unsigned short)((void *)sitnl_nlmsg_tail(_msg) - (void *)_nest); \
6666
}
6767

68+
int netns_fd;
69+
6870
/* This function was originally implemented as a macro, but compiling with
6971
* gcc and -O3 was getting confused about the math and thus raising
7072
* security warnings on subsequent memcpy() calls.
@@ -529,6 +531,114 @@ sitnl_route_save(struct nlmsghdr *n, void *arg)
529531
return 0;
530532
}
531533

534+
static int
535+
sitnl_link_get_ifindex(struct nlmsghdr *n, void *arg)
536+
{
537+
struct sitnl_link_req *res = arg;
538+
struct ifinfomsg *ifi;
539+
540+
if (n->nlmsg_type != RTM_NEWLINK)
541+
return 1;
542+
543+
ifi = NLMSG_DATA(n);
544+
res->i = *ifi;
545+
546+
return 0;
547+
}
548+
549+
static int
550+
get_ifindex_in_netns(const char *ifname, int netnsid)
551+
{
552+
struct sitnl_link_req req;
553+
struct sitnl_link_req res;
554+
int ret;
555+
556+
CLEAR(req);
557+
CLEAR(res);
558+
559+
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
560+
req.n.nlmsg_type = RTM_GETLINK;
561+
req.n.nlmsg_flags = NLM_F_REQUEST;
562+
563+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
564+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname) + 1);
565+
566+
ret = sitnl_send(&req.n, 0, 0, sitnl_link_get_ifindex, &res);
567+
568+
if (ret < 0)
569+
{
570+
goto err;
571+
}
572+
573+
return res.i.ifi_index;
574+
575+
err:
576+
return ret;
577+
}
578+
579+
int
580+
openvpn_if_nametoindex(const char *ifname, int netnsid)
581+
{
582+
if (netnsid < 0)
583+
{
584+
return if_nametoindex(ifname);
585+
}
586+
587+
return get_ifindex_in_netns(ifname, netnsid);
588+
}
589+
590+
int
591+
net_iface_move_netns(const char *iface,
592+
const char *netns_path)
593+
{
594+
struct sitnl_link_req req = {};
595+
int ret = -1;
596+
int ifindex;
597+
int netns_fd;
598+
599+
ASSERT(iface);
600+
ASSERT(netns_path);
601+
602+
ifindex = if_nametoindex(iface);
603+
if (ifindex == 0)
604+
{
605+
msg(M_ERR, "%s: if_nametoindex(%s) failed", __func__, iface);
606+
goto err;
607+
}
608+
609+
netns_fd = open(netns_path, O_RDONLY);
610+
if (netns_fd < 0)
611+
{
612+
msg(M_ERR, "%s: open(%s) failed: %s",
613+
__func__, netns_path, strerror(errno));
614+
goto err;
615+
}
616+
617+
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
618+
req.n.nlmsg_type = RTM_SETLINK;
619+
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
620+
621+
req.i.ifi_family = AF_UNSPEC;
622+
req.i.ifi_index = ifindex;
623+
624+
SITNL_ADDATTR(&req.n, sizeof(req),
625+
IFLA_NET_NS_FD,
626+
&netns_fd,
627+
sizeof(netns_fd));
628+
629+
msg(D_ROUTE, "%s: move %s to netns %s",
630+
__func__, iface, netns_path);
631+
632+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
633+
634+
err:
635+
if (netns_fd >= 0)
636+
{
637+
close(netns_fd);
638+
}
639+
return ret;
640+
}
641+
532642
static int
533643
sitnl_route_best_gw(sa_family_t af_family, const inet_address_t *dst, void *best_gw,
534644
char *best_iface)
@@ -661,7 +771,8 @@ int
661771
net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
662772
{
663773
struct sitnl_link_req req;
664-
int ifindex;
774+
int ifindex, netnsid = 0;
775+
int ret = -1;
665776

666777
CLEAR(req);
667778

@@ -671,7 +782,7 @@ net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
671782
return -EINVAL;
672783
}
673784

674-
ifindex = if_nametoindex(iface);
785+
ifindex = openvpn_if_nametoindex(iface, netnsid);
675786
if (ifindex == 0)
676787
{
677788
msg(M_WARN, "%s: rtnl: cannot get ifindex for %s: %s", __func__, iface, strerror(errno));
@@ -685,9 +796,11 @@ net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
685796
req.i.ifi_family = AF_PACKET;
686797
req.i.ifi_index = ifindex;
687798
req.i.ifi_change |= IFF_UP;
799+
688800
if (up)
689801
{
690802
req.i.ifi_flags |= IFF_UP;
803+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
691804
}
692805
else
693806
{
@@ -696,31 +809,36 @@ net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
696809

697810
msg(M_INFO, "%s: set %s %s", __func__, iface, up ? "up" : "down");
698811

699-
return sitnl_send(&req.n, 0, 0, NULL, NULL);
812+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
813+
814+
err:
815+
return ret;
700816
}
701817

702818
int
703819
net_iface_mtu_set(openvpn_net_ctx_t *ctx, const char *iface, uint32_t mtu)
704820
{
705821
struct sitnl_link_req req;
706822
int ifindex, ret = -1;
823+
int netnsid = 0;
707824

708825
CLEAR(req);
709826

710-
ifindex = if_nametoindex(iface);
827+
ifindex = openvpn_if_nametoindex(iface, netnsid);
711828
if (ifindex == 0)
712829
{
713830
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
714831
return -1;
715832
}
716833

717834
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
718-
req.n.nlmsg_flags = NLM_F_REQUEST;
835+
req.n.nlmsg_flags = 0; //NLM_F_REQUEST;
719836
req.n.nlmsg_type = RTM_NEWLINK;
720837

721838
req.i.ifi_family = AF_PACKET;
722839
req.i.ifi_index = ifindex;
723840

841+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
724842
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
725843

726844
msg(M_INFO, "%s: mtu %u for %s", __func__, mtu, iface);
@@ -734,25 +852,26 @@ int
734852
net_addr_ll_set(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface, uint8_t *addr)
735853
{
736854
struct sitnl_link_req req;
737-
int ifindex, ret = -1;
855+
int ifindex, ret = -1, netnsid = 0;
738856

739857
CLEAR(req);
740858

741-
ifindex = if_nametoindex(iface);
859+
ifindex = openvpn_if_nametoindex(iface, netnsid);
742860
if (ifindex == 0)
743861
{
744862
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
745863
return -1;
746864
}
747865

748866
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
749-
req.n.nlmsg_flags = NLM_F_REQUEST;
867+
req.n.nlmsg_flags = NLM_F_REQUEST;;
750868
req.n.nlmsg_type = RTM_NEWLINK;
751869

752870
req.i.ifi_family = AF_PACKET;
753871
req.i.ifi_index = ifindex;
754872

755873
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_ADDRESS, addr, OPENVPN_ETH_ALEN);
874+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
756875

757876
msg(M_INFO, "%s: lladdr " MAC_FMT " for %s", __func__, MAC_PRINT_ARG(addr), iface);
758877

@@ -768,12 +887,14 @@ sitnl_addr_set(uint16_t cmd, uint16_t flags, int ifindex, sa_family_t af_family,
768887
struct sitnl_addr_req req;
769888
uint32_t size;
770889
int ret = -EINVAL;
890+
int netnsid = 0;
771891

772892
CLEAR(req);
773893

774894
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
775895
req.n.nlmsg_type = cmd;
776896
req.n.nlmsg_flags = NLM_F_REQUEST | flags;
897+
// NLM_F_REQUEST | flags;
777898

778899
req.i.ifa_index = ifindex;
779900
ASSERT(af_family <= UINT8_MAX);
@@ -802,6 +923,8 @@ sitnl_addr_set(uint16_t cmd, uint16_t flags, int ifindex, sa_family_t af_family,
802923
ASSERT(prefixlen <= UINT8_MAX);
803924
req.i.ifa_prefixlen = (uint8_t)prefixlen;
804925

926+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
927+
805928
if (remote)
806929
{
807930
SITNL_ADDATTR(&req.n, sizeof(req), IFA_ADDRESS, remote, size);
@@ -984,7 +1107,7 @@ sitnl_addr_add(sa_family_t af_family, const char *iface, const inet_address_t *a
9841107
return -EINVAL;
9851108
}
9861109

987-
ifindex = if_nametoindex(iface);
1110+
ifindex = openvpn_if_nametoindex(iface, 0);
9881111
if (ifindex == 0)
9891112
{
9901113
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
@@ -1016,7 +1139,7 @@ sitnl_addr_del(sa_family_t af_family, const char *iface, inet_address_t *addr, i
10161139
return -EINVAL;
10171140
}
10181141

1019-
ifindex = if_nametoindex(iface);
1142+
ifindex = openvpn_if_nametoindex(iface, 0);
10201143
if (ifindex == 0)
10211144
{
10221145
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
@@ -1330,6 +1453,15 @@ net_iface_new(openvpn_net_ctx_t *ctx, const char *iface, const char *type, void
13301453

13311454
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface, strlen(iface) + 1);
13321455

1456+
netns_fd = open("/var/run/netns/ns-test", O_RDONLY);
1457+
if (netns_fd < 0)
1458+
{
1459+
msg(M_ERR, "%s: open(/var/run/netns/ns-test) failed: %s",
1460+
__func__, strerror(errno));
1461+
goto err;
1462+
}
1463+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_NET_NS_FD, &netns_fd, sizeof(netns_fd));
1464+
13331465
struct rtattr *linkinfo = SITNL_NEST(&req.n, sizeof(req), IFLA_LINKINFO);
13341466
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type) + 1);
13351467
#if defined(ENABLE_DCO)
@@ -1460,7 +1592,8 @@ int
14601592
net_iface_del(openvpn_net_ctx_t *ctx, const char *iface)
14611593
{
14621594
struct sitnl_link_req req = {};
1463-
int ifindex = if_nametoindex(iface);
1595+
int netnsid = 0, ret = -1;
1596+
int ifindex = openvpn_if_nametoindex(iface, netnsid);
14641597

14651598
if (!ifindex)
14661599
{
@@ -1471,12 +1604,17 @@ net_iface_del(openvpn_net_ctx_t *ctx, const char *iface)
14711604
req.n.nlmsg_flags = NLM_F_REQUEST;
14721605
req.n.nlmsg_type = RTM_DELLINK;
14731606

1607+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_NET_NS_FD, &netns_fd, sizeof(netns_fd));
1608+
14741609
req.i.ifi_family = AF_PACKET;
14751610
req.i.ifi_index = ifindex;
14761611

14771612
msg(D_ROUTE, "%s: delete %s", __func__, iface);
14781613

1479-
return sitnl_send(&req.n, 0, 0, NULL, NULL);
1614+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
1615+
1616+
err:
1617+
return ret;
14801618
}
14811619

14821620
#endif /* !ENABLE_SITNL */

src/openvpn/networking_sitnl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,8 @@
2424
typedef char openvpn_net_iface_t;
2525
typedef void *openvpn_net_ctx_t;
2626

27+
int net_iface_move_netns(const char *ifname, const char *netns_path);
28+
29+
int openvpn_if_nametoindex(const char *ifname, int netnsid);
30+
2731
#endif /* NETWORKING_SITNL_H_ */

src/openvpn/tun.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2082,23 +2082,6 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
20822082
node = "/dev/net/tun";
20832083
}
20842084

2085-
#if defined(TARGET_LINUX) && defined(CLONE_NEWNET) && defined(__GLIBC__)
2086-
if (tt->options.netns)
2087-
{
2088-
int netns_fd = open(tt->options.netns, O_RDONLY);
2089-
if (netns_fd < 0)
2090-
{
2091-
msg(M_ERR, "ERROR: Cannot open netns %s", tt->options.netns);
2092-
}
2093-
2094-
if (setns(netns_fd, CLONE_NEWNET) < 0)
2095-
{
2096-
msg(M_ERR, "ERROR: setns()");
2097-
close(netns_fd);
2098-
}
2099-
}
2100-
#endif
2101-
21022085
/*
21032086
* Open the interface
21042087
*/
@@ -2152,6 +2135,24 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
21522135

21532136
msg(M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);
21542137

2138+
#if defined(TARGET_LINUX) && defined(CLONE_NEWNET) && defined(__GLIBC__)
2139+
if (tt->options.netns)
2140+
{
2141+
/*int netns_fd = open(tt->options.netns, O_RDONLY);
2142+
if (netns_fd < 0)
2143+
{
2144+
msg(M_ERR, "ERROR: Cannot open netns %s", tt->options.netns);
2145+
}*/
2146+
2147+
int ret = net_iface_move_netns(ifr.ifr_name, tt->options.netns);
2148+
2149+
if (ret < 0)
2150+
{
2151+
msg(M_ERR, "ERROR: switching netns");
2152+
}
2153+
}
2154+
#endif
2155+
21552156
/*
21562157
* Try making the TX send queue bigger
21572158
*/

0 commit comments

Comments
 (0)