Skip to content

Commit 63d0a98

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

3 files changed

Lines changed: 176 additions & 31 deletions

File tree

src/openvpn/networking_sitnl.c

Lines changed: 154 additions & 14 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,116 @@ 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+
printf("\nNETNS_IFINDEX: %d\n", res.i.ifi_index);
574+
return res.i.ifi_index;
575+
576+
err:
577+
return ret;
578+
}
579+
580+
int
581+
openvpn_if_nametoindex(const char *ifname, int netnsid)
582+
{
583+
if (netnsid < 0)
584+
{
585+
printf("\nclassic if_nametoindex()\n");
586+
return if_nametoindex(ifname);
587+
}
588+
589+
return get_ifindex_in_netns(ifname, netnsid);
590+
}
591+
592+
int
593+
net_iface_move_netns(const char *iface,
594+
const char *netns_path)
595+
{
596+
struct sitnl_link_req req = {};
597+
int ret = -1;
598+
int ifindex;
599+
int netns_fd;
600+
601+
ASSERT(iface);
602+
ASSERT(netns_path);
603+
604+
ifindex = if_nametoindex(iface);
605+
if (ifindex == 0)
606+
{
607+
msg(M_ERR, "%s: if_nametoindex(%s) failed", __func__, iface);
608+
goto err;
609+
}
610+
611+
netns_fd = open(netns_path, O_RDONLY);
612+
if (netns_fd < 0)
613+
{
614+
msg(M_ERR, "%s: open(%s) failed: %s",
615+
__func__, netns_path, strerror(errno));
616+
goto err;
617+
}
618+
619+
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
620+
req.n.nlmsg_type = RTM_SETLINK;
621+
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
622+
623+
req.i.ifi_family = AF_UNSPEC;
624+
req.i.ifi_index = ifindex;
625+
626+
SITNL_ADDATTR(&req.n, sizeof(req),
627+
IFLA_NET_NS_FD,
628+
&netns_fd,
629+
sizeof(netns_fd));
630+
631+
msg(D_ROUTE, "%s: move %s to netns %s",
632+
__func__, iface, netns_path);
633+
634+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
635+
636+
err:
637+
if (netns_fd >= 0)
638+
{
639+
close(netns_fd);
640+
}
641+
return ret;
642+
}
643+
532644
static int
533645
sitnl_route_best_gw(sa_family_t af_family, const inet_address_t *dst, void *best_gw,
534646
char *best_iface)
@@ -661,7 +773,8 @@ int
661773
net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
662774
{
663775
struct sitnl_link_req req;
664-
int ifindex;
776+
int ifindex, netnsid = 0;
777+
int ret = -1;
665778

666779
CLEAR(req);
667780

@@ -671,23 +784,25 @@ net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
671784
return -EINVAL;
672785
}
673786

674-
ifindex = if_nametoindex(iface);
787+
ifindex = openvpn_if_nametoindex(iface, netnsid);
675788
if (ifindex == 0)
676789
{
677790
msg(M_WARN, "%s: rtnl: cannot get ifindex for %s: %s", __func__, iface, strerror(errno));
678791
return -ENOENT;
679792
}
680793

681794
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
682-
req.n.nlmsg_flags = NLM_F_REQUEST;
795+
req.n.nlmsg_flags = 0;
683796
req.n.nlmsg_type = RTM_NEWLINK;
684797

685798
req.i.ifi_family = AF_PACKET;
686799
req.i.ifi_index = ifindex;
687800
req.i.ifi_change |= IFF_UP;
801+
688802
if (up)
689803
{
690804
req.i.ifi_flags |= IFF_UP;
805+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
691806
}
692807
else
693808
{
@@ -696,31 +811,36 @@ net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
696811

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

699-
return sitnl_send(&req.n, 0, 0, NULL, NULL);
814+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
815+
816+
err:
817+
return ret;
700818
}
701819

702820
int
703821
net_iface_mtu_set(openvpn_net_ctx_t *ctx, const char *iface, uint32_t mtu)
704822
{
705823
struct sitnl_link_req req;
706824
int ifindex, ret = -1;
825+
int netnsid = 0;
707826

708827
CLEAR(req);
709828

710-
ifindex = if_nametoindex(iface);
829+
ifindex = openvpn_if_nametoindex(iface, netnsid);
711830
if (ifindex == 0)
712831
{
713832
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
714833
return -1;
715834
}
716835

717836
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
718-
req.n.nlmsg_flags = NLM_F_REQUEST;
837+
req.n.nlmsg_flags = 0;
719838
req.n.nlmsg_type = RTM_NEWLINK;
720839

721840
req.i.ifi_family = AF_PACKET;
722841
req.i.ifi_index = ifindex;
723842

843+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
724844
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
725845

726846
msg(M_INFO, "%s: mtu %u for %s", __func__, mtu, iface);
@@ -734,25 +854,26 @@ int
734854
net_addr_ll_set(openvpn_net_ctx_t *ctx, const openvpn_net_iface_t *iface, uint8_t *addr)
735855
{
736856
struct sitnl_link_req req;
737-
int ifindex, ret = -1;
857+
int ifindex, ret = -1, netnsid = 0;
738858

739859
CLEAR(req);
740860

741-
ifindex = if_nametoindex(iface);
861+
ifindex = openvpn_if_nametoindex(iface, netnsid);
742862
if (ifindex == 0)
743863
{
744864
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
745865
return -1;
746866
}
747867

748868
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
749-
req.n.nlmsg_flags = NLM_F_REQUEST;
869+
req.n.nlmsg_flags = 0;
750870
req.n.nlmsg_type = RTM_NEWLINK;
751871

752872
req.i.ifi_family = AF_PACKET;
753873
req.i.ifi_index = ifindex;
754874

755875
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_ADDRESS, addr, OPENVPN_ETH_ALEN);
876+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
756877

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

@@ -768,12 +889,14 @@ sitnl_addr_set(uint16_t cmd, uint16_t flags, int ifindex, sa_family_t af_family,
768889
struct sitnl_addr_req req;
769890
uint32_t size;
770891
int ret = -EINVAL;
892+
int netnsid = 0;
771893

772894
CLEAR(req);
773895

774896
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
775897
req.n.nlmsg_type = cmd;
776-
req.n.nlmsg_flags = NLM_F_REQUEST | flags;
898+
req.n.nlmsg_flags = 0;
899+
// NLM_F_REQUEST | flags;
777900

778901
req.i.ifa_index = ifindex;
779902
ASSERT(af_family <= UINT8_MAX);
@@ -802,6 +925,8 @@ sitnl_addr_set(uint16_t cmd, uint16_t flags, int ifindex, sa_family_t af_family,
802925
ASSERT(prefixlen <= UINT8_MAX);
803926
req.i.ifa_prefixlen = (uint8_t)prefixlen;
804927

928+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_TARGET_NETNSID, &netnsid, sizeof(int));
929+
805930
if (remote)
806931
{
807932
SITNL_ADDATTR(&req.n, sizeof(req), IFA_ADDRESS, remote, size);
@@ -984,7 +1109,7 @@ sitnl_addr_add(sa_family_t af_family, const char *iface, const inet_address_t *a
9841109
return -EINVAL;
9851110
}
9861111

987-
ifindex = if_nametoindex(iface);
1112+
ifindex = openvpn_if_nametoindex(iface, 0);
9881113
if (ifindex == 0)
9891114
{
9901115
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
@@ -1016,7 +1141,7 @@ sitnl_addr_del(sa_family_t af_family, const char *iface, inet_address_t *addr, i
10161141
return -EINVAL;
10171142
}
10181143

1019-
ifindex = if_nametoindex(iface);
1144+
ifindex = openvpn_if_nametoindex(iface, 0);
10201145
if (ifindex == 0)
10211146
{
10221147
msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__, iface);
@@ -1330,6 +1455,15 @@ net_iface_new(openvpn_net_ctx_t *ctx, const char *iface, const char *type, void
13301455

13311456
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_IFNAME, iface, strlen(iface) + 1);
13321457

1458+
netns_fd = open("/var/run/netns/ns-test", O_RDONLY);
1459+
if (netns_fd < 0)
1460+
{
1461+
msg(M_ERR, "%s: open(/var/run/netns/ns-test) failed: %s",
1462+
__func__, strerror(errno));
1463+
goto err;
1464+
}
1465+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_NET_NS_FD, &netns_fd, sizeof(netns_fd));
1466+
13331467
struct rtattr *linkinfo = SITNL_NEST(&req.n, sizeof(req), IFLA_LINKINFO);
13341468
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_INFO_KIND, type, strlen(type) + 1);
13351469
#if defined(ENABLE_DCO)
@@ -1460,7 +1594,8 @@ int
14601594
net_iface_del(openvpn_net_ctx_t *ctx, const char *iface)
14611595
{
14621596
struct sitnl_link_req req = {};
1463-
int ifindex = if_nametoindex(iface);
1597+
int netnsid = 0, ret = -1;
1598+
int ifindex = openvpn_if_nametoindex(iface, netnsid);
14641599

14651600
if (!ifindex)
14661601
{
@@ -1471,12 +1606,17 @@ net_iface_del(openvpn_net_ctx_t *ctx, const char *iface)
14711606
req.n.nlmsg_flags = NLM_F_REQUEST;
14721607
req.n.nlmsg_type = RTM_DELLINK;
14731608

1609+
SITNL_ADDATTR(&req.n, sizeof(req), IFLA_NET_NS_FD, &netns_fd, sizeof(netns_fd));
1610+
14741611
req.i.ifi_family = AF_PACKET;
14751612
req.i.ifi_index = ifindex;
14761613

14771614
msg(D_ROUTE, "%s: delete %s", __func__, iface);
14781615

1479-
return sitnl_send(&req.n, 0, 0, NULL, NULL);
1616+
ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
1617+
1618+
err:
1619+
return ret;
14801620
}
14811621

14821622
#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)