@@ -4491,6 +4491,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
44914491 [IFA_CACHEINFO ] = { .len = sizeof (struct ifa_cacheinfo ) },
44924492 [IFA_FLAGS ] = { .len = sizeof (u32 ) },
44934493 [IFA_RT_PRIORITY ] = { .len = sizeof (u32 ) },
4494+ [IFA_TARGET_NETNSID ] = { .type = NLA_S32 },
44944495};
44954496
44964497static int
@@ -4794,7 +4795,8 @@ static inline int inet6_ifaddr_msgsize(void)
47944795}
47954796
47964797static int inet6_fill_ifaddr (struct sk_buff * skb , struct inet6_ifaddr * ifa ,
4797- u32 portid , u32 seq , int event , unsigned int flags )
4798+ u32 portid , u32 seq , int event , unsigned int flags ,
4799+ int netnsid )
47984800{
47994801 struct nlmsghdr * nlh ;
48004802 u32 preferred , valid ;
@@ -4806,6 +4808,9 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
48064808 put_ifaddrmsg (nlh , ifa -> prefix_len , ifa -> flags , rt_scope (ifa -> scope ),
48074809 ifa -> idev -> dev -> ifindex );
48084810
4811+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4812+ goto error ;
4813+
48094814 if (!((ifa -> flags & IFA_F_PERMANENT ) &&
48104815 (ifa -> prefered_lft == INFINITY_LIFE_TIME ))) {
48114816 preferred = ifa -> prefered_lft ;
@@ -4855,7 +4860,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
48554860}
48564861
48574862static int inet6_fill_ifmcaddr (struct sk_buff * skb , struct ifmcaddr6 * ifmca ,
4858- u32 portid , u32 seq , int event , u16 flags )
4863+ u32 portid , u32 seq , int event , u16 flags ,
4864+ int netnsid )
48594865{
48604866 struct nlmsghdr * nlh ;
48614867 u8 scope = RT_SCOPE_UNIVERSE ;
@@ -4868,6 +4874,9 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
48684874 if (!nlh )
48694875 return - EMSGSIZE ;
48704876
4877+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4878+ return - EMSGSIZE ;
4879+
48714880 put_ifaddrmsg (nlh , 128 , IFA_F_PERMANENT , scope , ifindex );
48724881 if (nla_put_in6_addr (skb , IFA_MULTICAST , & ifmca -> mca_addr ) < 0 ||
48734882 put_cacheinfo (skb , ifmca -> mca_cstamp , ifmca -> mca_tstamp ,
@@ -4881,7 +4890,8 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
48814890}
48824891
48834892static int inet6_fill_ifacaddr (struct sk_buff * skb , struct ifacaddr6 * ifaca ,
4884- u32 portid , u32 seq , int event , unsigned int flags )
4893+ u32 portid , u32 seq , int event ,
4894+ unsigned int flags , int netnsid )
48854895{
48864896 struct net_device * dev = fib6_info_nh_dev (ifaca -> aca_rt );
48874897 int ifindex = dev ? dev -> ifindex : 1 ;
@@ -4895,6 +4905,9 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
48954905 if (!nlh )
48964906 return - EMSGSIZE ;
48974907
4908+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4909+ return - EMSGSIZE ;
4910+
48984911 put_ifaddrmsg (nlh , 128 , IFA_F_PERMANENT , scope , ifindex );
48994912 if (nla_put_in6_addr (skb , IFA_ANYCAST , & ifaca -> aca_addr ) < 0 ||
49004913 put_cacheinfo (skb , ifaca -> aca_cstamp , ifaca -> aca_tstamp ,
@@ -4916,7 +4929,7 @@ enum addr_type_t {
49164929/* called with rcu_read_lock() */
49174930static int in6_dump_addrs (struct inet6_dev * idev , struct sk_buff * skb ,
49184931 struct netlink_callback * cb , enum addr_type_t type ,
4919- int s_ip_idx , int * p_ip_idx )
4932+ int s_ip_idx , int * p_ip_idx , int netnsid )
49204933{
49214934 struct ifmcaddr6 * ifmca ;
49224935 struct ifacaddr6 * ifaca ;
@@ -4936,7 +4949,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
49364949 NETLINK_CB (cb -> skb ).portid ,
49374950 cb -> nlh -> nlmsg_seq ,
49384951 RTM_NEWADDR ,
4939- NLM_F_MULTI );
4952+ NLM_F_MULTI , netnsid );
49404953 if (err < 0 )
49414954 break ;
49424955 nl_dump_check_consistent (cb , nlmsg_hdr (skb ));
@@ -4953,7 +4966,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
49534966 NETLINK_CB (cb -> skb ).portid ,
49544967 cb -> nlh -> nlmsg_seq ,
49554968 RTM_GETMULTICAST ,
4956- NLM_F_MULTI );
4969+ NLM_F_MULTI , netnsid );
49574970 if (err < 0 )
49584971 break ;
49594972 }
@@ -4968,7 +4981,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
49684981 NETLINK_CB (cb -> skb ).portid ,
49694982 cb -> nlh -> nlmsg_seq ,
49704983 RTM_GETANYCAST ,
4971- NLM_F_MULTI );
4984+ NLM_F_MULTI , netnsid );
49724985 if (err < 0 )
49734986 break ;
49744987 }
@@ -4985,6 +4998,9 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
49854998 enum addr_type_t type )
49864999{
49875000 struct net * net = sock_net (skb -> sk );
5001+ struct nlattr * tb [IFA_MAX + 1 ];
5002+ struct net * tgt_net = net ;
5003+ int netnsid = -1 ;
49885004 int h , s_h ;
49895005 int idx , ip_idx ;
49905006 int s_idx , s_ip_idx ;
@@ -4996,11 +5012,22 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
49965012 s_idx = idx = cb -> args [1 ];
49975013 s_ip_idx = ip_idx = cb -> args [2 ];
49985014
5015+ if (nlmsg_parse (cb -> nlh , sizeof (struct ifaddrmsg ), tb , IFA_MAX ,
5016+ ifa_ipv6_policy , NULL ) >= 0 ) {
5017+ if (tb [IFA_TARGET_NETNSID ]) {
5018+ netnsid = nla_get_s32 (tb [IFA_TARGET_NETNSID ]);
5019+
5020+ tgt_net = rtnl_get_net_ns_capable (skb -> sk , netnsid );
5021+ if (IS_ERR (tgt_net ))
5022+ return PTR_ERR (tgt_net );
5023+ }
5024+ }
5025+
49995026 rcu_read_lock ();
5000- cb -> seq = atomic_read (& net -> ipv6 .dev_addr_genid ) ^ net -> dev_base_seq ;
5027+ cb -> seq = atomic_read (& tgt_net -> ipv6 .dev_addr_genid ) ^ tgt_net -> dev_base_seq ;
50015028 for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
50025029 idx = 0 ;
5003- head = & net -> dev_index_head [h ];
5030+ head = & tgt_net -> dev_index_head [h ];
50045031 hlist_for_each_entry_rcu (dev , head , index_hlist ) {
50055032 if (idx < s_idx )
50065033 goto cont ;
@@ -5012,7 +5039,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
50125039 goto cont ;
50135040
50145041 if (in6_dump_addrs (idev , skb , cb , type ,
5015- s_ip_idx , & ip_idx ) < 0 )
5042+ s_ip_idx , & ip_idx , netnsid ) < 0 )
50165043 goto done ;
50175044cont :
50185045 idx ++ ;
@@ -5023,6 +5050,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
50235050 cb -> args [0 ] = h ;
50245051 cb -> args [1 ] = idx ;
50255052 cb -> args [2 ] = ip_idx ;
5053+ if (netnsid >= 0 )
5054+ put_net (tgt_net );
50265055
50275056 return skb -> len ;
50285057}
@@ -5053,28 +5082,39 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
50535082 struct netlink_ext_ack * extack )
50545083{
50555084 struct net * net = sock_net (in_skb -> sk );
5085+ struct net * tgt_net = net ;
50565086 struct ifaddrmsg * ifm ;
50575087 struct nlattr * tb [IFA_MAX + 1 ];
50585088 struct in6_addr * addr = NULL , * peer ;
50595089 struct net_device * dev = NULL ;
50605090 struct inet6_ifaddr * ifa ;
50615091 struct sk_buff * skb ;
5092+ int netnsid = -1 ;
50625093 int err ;
50635094
50645095 err = nlmsg_parse (nlh , sizeof (* ifm ), tb , IFA_MAX , ifa_ipv6_policy ,
50655096 extack );
50665097 if (err < 0 )
50675098 return err ;
50685099
5100+ if (tb [IFA_TARGET_NETNSID ]) {
5101+ netnsid = nla_get_s32 (tb [IFA_TARGET_NETNSID ]);
5102+
5103+ tgt_net = rtnl_get_net_ns_capable (NETLINK_CB (in_skb ).sk ,
5104+ netnsid );
5105+ if (IS_ERR (tgt_net ))
5106+ return PTR_ERR (tgt_net );
5107+ }
5108+
50695109 addr = extract_addr (tb [IFA_ADDRESS ], tb [IFA_LOCAL ], & peer );
50705110 if (!addr )
50715111 return - EINVAL ;
50725112
50735113 ifm = nlmsg_data (nlh );
50745114 if (ifm -> ifa_index )
5075- dev = dev_get_by_index (net , ifm -> ifa_index );
5115+ dev = dev_get_by_index (tgt_net , ifm -> ifa_index );
50765116
5077- ifa = ipv6_get_ifaddr (net , addr , dev , 1 );
5117+ ifa = ipv6_get_ifaddr (tgt_net , addr , dev , 1 );
50785118 if (!ifa ) {
50795119 err = - EADDRNOTAVAIL ;
50805120 goto errout ;
@@ -5087,19 +5127,22 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
50875127 }
50885128
50895129 err = inet6_fill_ifaddr (skb , ifa , NETLINK_CB (in_skb ).portid ,
5090- nlh -> nlmsg_seq , RTM_NEWADDR , 0 );
5130+ nlh -> nlmsg_seq , RTM_NEWADDR , 0 , netnsid );
50915131 if (err < 0 ) {
50925132 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
50935133 WARN_ON (err == - EMSGSIZE );
50945134 kfree_skb (skb );
50955135 goto errout_ifa ;
50965136 }
5097- err = rtnl_unicast (skb , net , NETLINK_CB (in_skb ).portid );
5137+ err = rtnl_unicast (skb , tgt_net , NETLINK_CB (in_skb ).portid );
50985138errout_ifa :
50995139 in6_ifa_put (ifa );
51005140errout :
51015141 if (dev )
51025142 dev_put (dev );
5143+ if (netnsid >= 0 )
5144+ put_net (tgt_net );
5145+
51035146 return err ;
51045147}
51055148
@@ -5113,7 +5156,7 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
51135156 if (!skb )
51145157 goto errout ;
51155158
5116- err = inet6_fill_ifaddr (skb , ifa , 0 , 0 , event , 0 );
5159+ err = inet6_fill_ifaddr (skb , ifa , 0 , 0 , event , 0 , -1 );
51175160 if (err < 0 ) {
51185161 /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
51195162 WARN_ON (err == - EMSGSIZE );
0 commit comments