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+
532644static int
533645sitnl_route_best_gw (sa_family_t af_family , const inet_address_t * dst , void * best_gw ,
534646 char * best_iface )
661773net_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
702820int
703821net_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
734854net_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
14601594net_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 */
0 commit comments