@@ -4491,6 +4491,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
4491
4491
[IFA_CACHEINFO ] = { .len = sizeof (struct ifa_cacheinfo ) },
4492
4492
[IFA_FLAGS ] = { .len = sizeof (u32 ) },
4493
4493
[IFA_RT_PRIORITY ] = { .len = sizeof (u32 ) },
4494
+ [IFA_TARGET_NETNSID ] = { .type = NLA_S32 },
4494
4495
};
4495
4496
4496
4497
static int
@@ -4794,7 +4795,8 @@ static inline int inet6_ifaddr_msgsize(void)
4794
4795
}
4795
4796
4796
4797
static 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 )
4798
4800
{
4799
4801
struct nlmsghdr * nlh ;
4800
4802
u32 preferred , valid ;
@@ -4806,6 +4808,9 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
4806
4808
put_ifaddrmsg (nlh , ifa -> prefix_len , ifa -> flags , rt_scope (ifa -> scope ),
4807
4809
ifa -> idev -> dev -> ifindex );
4808
4810
4811
+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4812
+ goto error ;
4813
+
4809
4814
if (!((ifa -> flags & IFA_F_PERMANENT ) &&
4810
4815
(ifa -> prefered_lft == INFINITY_LIFE_TIME ))) {
4811
4816
preferred = ifa -> prefered_lft ;
@@ -4855,7 +4860,8 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
4855
4860
}
4856
4861
4857
4862
static 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 )
4859
4865
{
4860
4866
struct nlmsghdr * nlh ;
4861
4867
u8 scope = RT_SCOPE_UNIVERSE ;
@@ -4868,6 +4874,9 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
4868
4874
if (!nlh )
4869
4875
return - EMSGSIZE ;
4870
4876
4877
+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4878
+ return - EMSGSIZE ;
4879
+
4871
4880
put_ifaddrmsg (nlh , 128 , IFA_F_PERMANENT , scope , ifindex );
4872
4881
if (nla_put_in6_addr (skb , IFA_MULTICAST , & ifmca -> mca_addr ) < 0 ||
4873
4882
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,
4881
4890
}
4882
4891
4883
4892
static 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 )
4885
4895
{
4886
4896
struct net_device * dev = fib6_info_nh_dev (ifaca -> aca_rt );
4887
4897
int ifindex = dev ? dev -> ifindex : 1 ;
@@ -4895,6 +4905,9 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
4895
4905
if (!nlh )
4896
4906
return - EMSGSIZE ;
4897
4907
4908
+ if (netnsid >= 0 && nla_put_s32 (skb , IFA_TARGET_NETNSID , netnsid ))
4909
+ return - EMSGSIZE ;
4910
+
4898
4911
put_ifaddrmsg (nlh , 128 , IFA_F_PERMANENT , scope , ifindex );
4899
4912
if (nla_put_in6_addr (skb , IFA_ANYCAST , & ifaca -> aca_addr ) < 0 ||
4900
4913
put_cacheinfo (skb , ifaca -> aca_cstamp , ifaca -> aca_tstamp ,
@@ -4916,7 +4929,7 @@ enum addr_type_t {
4916
4929
/* called with rcu_read_lock() */
4917
4930
static int in6_dump_addrs (struct inet6_dev * idev , struct sk_buff * skb ,
4918
4931
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 )
4920
4933
{
4921
4934
struct ifmcaddr6 * ifmca ;
4922
4935
struct ifacaddr6 * ifaca ;
@@ -4936,7 +4949,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
4936
4949
NETLINK_CB (cb -> skb ).portid ,
4937
4950
cb -> nlh -> nlmsg_seq ,
4938
4951
RTM_NEWADDR ,
4939
- NLM_F_MULTI );
4952
+ NLM_F_MULTI , netnsid );
4940
4953
if (err < 0 )
4941
4954
break ;
4942
4955
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,
4953
4966
NETLINK_CB (cb -> skb ).portid ,
4954
4967
cb -> nlh -> nlmsg_seq ,
4955
4968
RTM_GETMULTICAST ,
4956
- NLM_F_MULTI );
4969
+ NLM_F_MULTI , netnsid );
4957
4970
if (err < 0 )
4958
4971
break ;
4959
4972
}
@@ -4968,7 +4981,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
4968
4981
NETLINK_CB (cb -> skb ).portid ,
4969
4982
cb -> nlh -> nlmsg_seq ,
4970
4983
RTM_GETANYCAST ,
4971
- NLM_F_MULTI );
4984
+ NLM_F_MULTI , netnsid );
4972
4985
if (err < 0 )
4973
4986
break ;
4974
4987
}
@@ -4985,6 +4998,9 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
4985
4998
enum addr_type_t type )
4986
4999
{
4987
5000
struct net * net = sock_net (skb -> sk );
5001
+ struct nlattr * tb [IFA_MAX + 1 ];
5002
+ struct net * tgt_net = net ;
5003
+ int netnsid = -1 ;
4988
5004
int h , s_h ;
4989
5005
int idx , ip_idx ;
4990
5006
int s_idx , s_ip_idx ;
@@ -4996,11 +5012,22 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
4996
5012
s_idx = idx = cb -> args [1 ];
4997
5013
s_ip_idx = ip_idx = cb -> args [2 ];
4998
5014
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
+
4999
5026
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 ;
5001
5028
for (h = s_h ; h < NETDEV_HASHENTRIES ; h ++ , s_idx = 0 ) {
5002
5029
idx = 0 ;
5003
- head = & net -> dev_index_head [h ];
5030
+ head = & tgt_net -> dev_index_head [h ];
5004
5031
hlist_for_each_entry_rcu (dev , head , index_hlist ) {
5005
5032
if (idx < s_idx )
5006
5033
goto cont ;
@@ -5012,7 +5039,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
5012
5039
goto cont ;
5013
5040
5014
5041
if (in6_dump_addrs (idev , skb , cb , type ,
5015
- s_ip_idx , & ip_idx ) < 0 )
5042
+ s_ip_idx , & ip_idx , netnsid ) < 0 )
5016
5043
goto done ;
5017
5044
cont :
5018
5045
idx ++ ;
@@ -5023,6 +5050,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
5023
5050
cb -> args [0 ] = h ;
5024
5051
cb -> args [1 ] = idx ;
5025
5052
cb -> args [2 ] = ip_idx ;
5053
+ if (netnsid >= 0 )
5054
+ put_net (tgt_net );
5026
5055
5027
5056
return skb -> len ;
5028
5057
}
@@ -5053,28 +5082,39 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
5053
5082
struct netlink_ext_ack * extack )
5054
5083
{
5055
5084
struct net * net = sock_net (in_skb -> sk );
5085
+ struct net * tgt_net = net ;
5056
5086
struct ifaddrmsg * ifm ;
5057
5087
struct nlattr * tb [IFA_MAX + 1 ];
5058
5088
struct in6_addr * addr = NULL , * peer ;
5059
5089
struct net_device * dev = NULL ;
5060
5090
struct inet6_ifaddr * ifa ;
5061
5091
struct sk_buff * skb ;
5092
+ int netnsid = -1 ;
5062
5093
int err ;
5063
5094
5064
5095
err = nlmsg_parse (nlh , sizeof (* ifm ), tb , IFA_MAX , ifa_ipv6_policy ,
5065
5096
extack );
5066
5097
if (err < 0 )
5067
5098
return err ;
5068
5099
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
+
5069
5109
addr = extract_addr (tb [IFA_ADDRESS ], tb [IFA_LOCAL ], & peer );
5070
5110
if (!addr )
5071
5111
return - EINVAL ;
5072
5112
5073
5113
ifm = nlmsg_data (nlh );
5074
5114
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 );
5076
5116
5077
- ifa = ipv6_get_ifaddr (net , addr , dev , 1 );
5117
+ ifa = ipv6_get_ifaddr (tgt_net , addr , dev , 1 );
5078
5118
if (!ifa ) {
5079
5119
err = - EADDRNOTAVAIL ;
5080
5120
goto errout ;
@@ -5087,19 +5127,22 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
5087
5127
}
5088
5128
5089
5129
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 );
5091
5131
if (err < 0 ) {
5092
5132
/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5093
5133
WARN_ON (err == - EMSGSIZE );
5094
5134
kfree_skb (skb );
5095
5135
goto errout_ifa ;
5096
5136
}
5097
- err = rtnl_unicast (skb , net , NETLINK_CB (in_skb ).portid );
5137
+ err = rtnl_unicast (skb , tgt_net , NETLINK_CB (in_skb ).portid );
5098
5138
errout_ifa :
5099
5139
in6_ifa_put (ifa );
5100
5140
errout :
5101
5141
if (dev )
5102
5142
dev_put (dev );
5143
+ if (netnsid >= 0 )
5144
+ put_net (tgt_net );
5145
+
5103
5146
return err ;
5104
5147
}
5105
5148
@@ -5113,7 +5156,7 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
5113
5156
if (!skb )
5114
5157
goto errout ;
5115
5158
5116
- err = inet6_fill_ifaddr (skb , ifa , 0 , 0 , event , 0 );
5159
+ err = inet6_fill_ifaddr (skb , ifa , 0 , 0 , event , 0 , -1 );
5117
5160
if (err < 0 ) {
5118
5161
/* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
5119
5162
WARN_ON (err == - EMSGSIZE );
0 commit comments