@@ -1063,20 +1063,28 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
10631063 struct fib6_info * f6i = NULL ;
10641064 int err = 0 ;
10651065
1066- if (addr_type == IPV6_ADDR_ANY ||
1067- (addr_type & IPV6_ADDR_MULTICAST &&
1068- !(cfg -> ifa_flags & IFA_F_MCAUTOJOIN )) ||
1069- (!(idev -> dev -> flags & IFF_LOOPBACK ) &&
1070- !netif_is_l3_master (idev -> dev ) &&
1071- addr_type & IPV6_ADDR_LOOPBACK ))
1066+ if (addr_type == IPV6_ADDR_ANY ) {
1067+ NL_SET_ERR_MSG_MOD (extack , "Invalid address" );
10721068 return ERR_PTR (- EADDRNOTAVAIL );
1069+ } else if (addr_type & IPV6_ADDR_MULTICAST &&
1070+ !(cfg -> ifa_flags & IFA_F_MCAUTOJOIN )) {
1071+ NL_SET_ERR_MSG_MOD (extack , "Cannot assign multicast address without \"IFA_F_MCAUTOJOIN\" flag" );
1072+ return ERR_PTR (- EADDRNOTAVAIL );
1073+ } else if (!(idev -> dev -> flags & IFF_LOOPBACK ) &&
1074+ !netif_is_l3_master (idev -> dev ) &&
1075+ addr_type & IPV6_ADDR_LOOPBACK ) {
1076+ NL_SET_ERR_MSG_MOD (extack , "Cannot assign loopback address on this device" );
1077+ return ERR_PTR (- EADDRNOTAVAIL );
1078+ }
10731079
10741080 if (idev -> dead ) {
1075- err = - ENODEV ; /*XXX*/
1081+ NL_SET_ERR_MSG_MOD (extack , "device is going away" );
1082+ err = - ENODEV ;
10761083 goto out ;
10771084 }
10781085
10791086 if (idev -> cnf .disable_ipv6 ) {
1087+ NL_SET_ERR_MSG_MOD (extack , "IPv6 is disabled on this device" );
10801088 err = - EACCES ;
10811089 goto out ;
10821090 }
@@ -1103,7 +1111,7 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
11031111 goto out ;
11041112 }
11051113
1106- f6i = addrconf_f6i_alloc (net , idev , cfg -> pfx , false, gfp_flags );
1114+ f6i = addrconf_f6i_alloc (net , idev , cfg -> pfx , false, gfp_flags , extack );
11071115 if (IS_ERR (f6i )) {
11081116 err = PTR_ERR (f6i );
11091117 f6i = NULL ;
@@ -2927,30 +2935,40 @@ static int inet6_addr_add(struct net *net, int ifindex,
29272935
29282936 ASSERT_RTNL ();
29292937
2930- if (cfg -> plen > 128 )
2938+ if (cfg -> plen > 128 ) {
2939+ NL_SET_ERR_MSG_MOD (extack , "Invalid prefix length" );
29312940 return - EINVAL ;
2941+ }
29322942
29332943 /* check the lifetime */
2934- if (!cfg -> valid_lft || cfg -> preferred_lft > cfg -> valid_lft )
2944+ if (!cfg -> valid_lft || cfg -> preferred_lft > cfg -> valid_lft ) {
2945+ NL_SET_ERR_MSG_MOD (extack , "address lifetime invalid" );
29352946 return - EINVAL ;
2947+ }
29362948
2937- if (cfg -> ifa_flags & IFA_F_MANAGETEMPADDR && cfg -> plen != 64 )
2949+ if (cfg -> ifa_flags & IFA_F_MANAGETEMPADDR && cfg -> plen != 64 ) {
2950+ NL_SET_ERR_MSG_MOD (extack , "address with \"mngtmpaddr\" flag must have a prefix length of 64" );
29382951 return - EINVAL ;
2952+ }
29392953
29402954 dev = __dev_get_by_index (net , ifindex );
29412955 if (!dev )
29422956 return - ENODEV ;
29432957
29442958 idev = addrconf_add_dev (dev );
2945- if (IS_ERR (idev ))
2959+ if (IS_ERR (idev )) {
2960+ NL_SET_ERR_MSG_MOD (extack , "IPv6 is disabled on this device" );
29462961 return PTR_ERR (idev );
2962+ }
29472963
29482964 if (cfg -> ifa_flags & IFA_F_MCAUTOJOIN ) {
29492965 int ret = ipv6_mc_config (net -> ipv6 .mc_autojoin_sk ,
29502966 true, cfg -> pfx , ifindex );
29512967
2952- if (ret < 0 )
2968+ if (ret < 0 ) {
2969+ NL_SET_ERR_MSG_MOD (extack , "Multicast auto join failed" );
29532970 return ret ;
2971+ }
29542972 }
29552973
29562974 cfg -> scope = ipv6_addr_scope (cfg -> pfx );
@@ -3007,22 +3025,29 @@ static int inet6_addr_add(struct net *net, int ifindex,
30073025}
30083026
30093027static int inet6_addr_del (struct net * net , int ifindex , u32 ifa_flags ,
3010- const struct in6_addr * pfx , unsigned int plen )
3028+ const struct in6_addr * pfx , unsigned int plen ,
3029+ struct netlink_ext_ack * extack )
30113030{
30123031 struct inet6_ifaddr * ifp ;
30133032 struct inet6_dev * idev ;
30143033 struct net_device * dev ;
30153034
3016- if (plen > 128 )
3035+ if (plen > 128 ) {
3036+ NL_SET_ERR_MSG_MOD (extack , "Invalid prefix length" );
30173037 return - EINVAL ;
3038+ }
30183039
30193040 dev = __dev_get_by_index (net , ifindex );
3020- if (!dev )
3041+ if (!dev ) {
3042+ NL_SET_ERR_MSG_MOD (extack , "Unable to find the interface" );
30213043 return - ENODEV ;
3044+ }
30223045
30233046 idev = __in6_dev_get (dev );
3024- if (!idev )
3047+ if (!idev ) {
3048+ NL_SET_ERR_MSG_MOD (extack , "IPv6 is disabled on this device" );
30253049 return - ENXIO ;
3050+ }
30263051
30273052 read_lock_bh (& idev -> lock );
30283053 list_for_each_entry (ifp , & idev -> addr_list , if_list ) {
@@ -3045,6 +3070,8 @@ static int inet6_addr_del(struct net *net, int ifindex, u32 ifa_flags,
30453070 }
30463071 }
30473072 read_unlock_bh (& idev -> lock );
3073+
3074+ NL_SET_ERR_MSG_MOD (extack , "address not found" );
30483075 return - EADDRNOTAVAIL ;
30493076}
30503077
@@ -3087,7 +3114,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
30873114
30883115 rtnl_lock ();
30893116 err = inet6_addr_del (net , ireq .ifr6_ifindex , 0 , & ireq .ifr6_addr ,
3090- ireq .ifr6_prefixlen );
3117+ ireq .ifr6_prefixlen , NULL );
30913118 rtnl_unlock ();
30923119 return err ;
30933120}
@@ -3490,7 +3517,7 @@ static int fixup_permanent_addr(struct net *net,
34903517 struct fib6_info * f6i , * prev ;
34913518
34923519 f6i = addrconf_f6i_alloc (net , idev , & ifp -> addr , false,
3493- GFP_ATOMIC );
3520+ GFP_ATOMIC , NULL );
34943521 if (IS_ERR (f6i ))
34953522 return PTR_ERR (f6i );
34963523
@@ -4700,7 +4727,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
47004727 ifa_flags &= IFA_F_MANAGETEMPADDR ;
47014728
47024729 return inet6_addr_del (net , ifm -> ifa_index , ifa_flags , pfx ,
4703- ifm -> ifa_prefixlen );
4730+ ifm -> ifa_prefixlen , extack );
47044731}
47054732
47064733static int modify_prefix_route (struct inet6_ifaddr * ifp ,
@@ -4905,8 +4932,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
49054932 }
49064933
49074934 dev = __dev_get_by_index (net , ifm -> ifa_index );
4908- if (!dev )
4935+ if (!dev ) {
4936+ NL_SET_ERR_MSG_MOD (extack , "Unable to find the interface" );
49094937 return - ENODEV ;
4938+ }
49104939
49114940 if (tb [IFA_FLAGS ])
49124941 cfg .ifa_flags = nla_get_u32 (tb [IFA_FLAGS ]);
@@ -4941,10 +4970,12 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
49414970 }
49424971
49434972 if (nlh -> nlmsg_flags & NLM_F_EXCL ||
4944- !(nlh -> nlmsg_flags & NLM_F_REPLACE ))
4973+ !(nlh -> nlmsg_flags & NLM_F_REPLACE )) {
4974+ NL_SET_ERR_MSG_MOD (extack , "address already assigned" );
49454975 err = - EEXIST ;
4946- else
4976+ } else {
49474977 err = inet6_addr_modify (net , ifa , & cfg );
4978+ }
49484979
49494980 in6_ifa_put (ifa );
49504981
0 commit comments