aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index bb18b9c3a5cb..1e5a296d0a82 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2908,24 +2908,14 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2908 return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); 2908 return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
2909} 2909}
2910 2910
2911static int 2911static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 prefered_lft,
2912inet6_addr_modify(int ifindex, struct in6_addr *pfx, 2912 u32 valid_lft)
2913 __u32 prefered_lft, __u32 valid_lft)
2914{ 2913{
2915 struct inet6_ifaddr *ifp = NULL;
2916 struct net_device *dev;
2917 int ifa_flags = 0; 2914 int ifa_flags = 0;
2918 2915
2919 if ((dev = __dev_get_by_index(ifindex)) == NULL)
2920 return -ENODEV;
2921
2922 if (!valid_lft || (prefered_lft > valid_lft)) 2916 if (!valid_lft || (prefered_lft > valid_lft))
2923 return -EINVAL; 2917 return -EINVAL;
2924 2918
2925 ifp = ipv6_get_ifaddr(pfx, dev, 1);
2926 if (ifp == NULL)
2927 return -ENOENT;
2928
2929 if (valid_lft == INFINITY_LIFE_TIME) 2919 if (valid_lft == INFINITY_LIFE_TIME)
2930 ifa_flags = IFA_F_PERMANENT; 2920 ifa_flags = IFA_F_PERMANENT;
2931 else if (valid_lft >= 0x7FFFFFFF/HZ) 2921 else if (valid_lft >= 0x7FFFFFFF/HZ)
@@ -2947,7 +2937,6 @@ inet6_addr_modify(int ifindex, struct in6_addr *pfx,
2947 spin_unlock_bh(&ifp->lock); 2937 spin_unlock_bh(&ifp->lock);
2948 if (!(ifp->flags&IFA_F_TENTATIVE)) 2938 if (!(ifp->flags&IFA_F_TENTATIVE))
2949 ipv6_ifa_notify(0, ifp); 2939 ipv6_ifa_notify(0, ifp);
2950 in6_ifa_put(ifp);
2951 2940
2952 addrconf_verify(0); 2941 addrconf_verify(0);
2953 2942
@@ -2960,6 +2949,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2960 struct ifaddrmsg *ifm; 2949 struct ifaddrmsg *ifm;
2961 struct nlattr *tb[IFA_MAX+1]; 2950 struct nlattr *tb[IFA_MAX+1];
2962 struct in6_addr *pfx; 2951 struct in6_addr *pfx;
2952 struct inet6_ifaddr *ifa;
2953 struct net_device *dev;
2963 u32 valid_lft, preferred_lft; 2954 u32 valid_lft, preferred_lft;
2964 int err; 2955 int err;
2965 2956
@@ -2983,15 +2974,29 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
2983 valid_lft = INFINITY_LIFE_TIME; 2974 valid_lft = INFINITY_LIFE_TIME;
2984 } 2975 }
2985 2976
2986 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 2977 dev = __dev_get_by_index(ifm->ifa_index);
2987 err = inet6_addr_modify(ifm->ifa_index, pfx, 2978 if (dev == NULL)
2988 preferred_lft, valid_lft); 2979 return -ENODEV;
2989 if (err == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) 2980
2990 return err; 2981 ifa = ipv6_get_ifaddr(pfx, dev, 1);
2982 if (ifa == NULL) {
2983 /*
2984 * It would be best to check for !NLM_F_CREATE here but
2985 * userspace alreay relies on not having to provide this.
2986 */
2987 return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen,
2988 preferred_lft, valid_lft);
2991 } 2989 }
2992 2990
2993 return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, 2991 if (nlh->nlmsg_flags & NLM_F_EXCL ||
2994 preferred_lft, valid_lft); 2992 !(nlh->nlmsg_flags & NLM_F_REPLACE))
2993 err = -EEXIST;
2994 else
2995 err = inet6_addr_modify(ifa, preferred_lft, valid_lft);
2996
2997 in6_ifa_put(ifa);
2998
2999 return err;
2995} 3000}
2996 3001
2997static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags, 3002static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags,