aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/addrconf.c52
1 files changed, 24 insertions, 28 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 61627036eb2b..b2c38b3edb39 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3234,58 +3234,54 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
3234 return inet6_dump_addr(skb, cb, type); 3234 return inet6_dump_addr(skb, cb, type);
3235} 3235}
3236 3236
3237static int inet6_rtm_getaddr(struct sk_buff *in_skb, 3237static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
3238 struct nlmsghdr* nlh, void *arg) 3238 void *arg)
3239{ 3239{
3240 struct rtattr **rta = arg; 3240 struct ifaddrmsg *ifm;
3241 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 3241 struct nlattr *tb[IFA_MAX+1];
3242 struct in6_addr *addr = NULL; 3242 struct in6_addr *addr = NULL;
3243 struct net_device *dev = NULL; 3243 struct net_device *dev = NULL;
3244 struct inet6_ifaddr *ifa; 3244 struct inet6_ifaddr *ifa;
3245 struct sk_buff *skb; 3245 struct sk_buff *skb;
3246 int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); 3246 int payload = sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE;
3247 int err; 3247 int err;
3248 3248
3249 if (rta[IFA_ADDRESS-1]) { 3249 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
3250 if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr)) 3250 if (err < 0)
3251 return -EINVAL; 3251 goto errout;
3252 addr = RTA_DATA(rta[IFA_ADDRESS-1]); 3252
3253 } 3253 addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
3254 if (rta[IFA_LOCAL-1]) { 3254 if (addr == NULL) {
3255 if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) || 3255 err = -EINVAL;
3256 (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr)))) 3256 goto errout;
3257 return -EINVAL;
3258 addr = RTA_DATA(rta[IFA_LOCAL-1]);
3259 } 3257 }
3260 if (addr == NULL)
3261 return -EINVAL;
3262 3258
3259 ifm = nlmsg_data(nlh);
3263 if (ifm->ifa_index) 3260 if (ifm->ifa_index)
3264 dev = __dev_get_by_index(ifm->ifa_index); 3261 dev = __dev_get_by_index(ifm->ifa_index);
3265 3262
3266 if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) 3263 if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) {
3267 return -EADDRNOTAVAIL; 3264 err = -EADDRNOTAVAIL;
3265 goto errout;
3266 }
3268 3267
3269 if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) { 3268 if ((skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL)) == NULL) {
3270 err = -ENOBUFS; 3269 err = -ENOBUFS;
3271 goto out; 3270 goto errout_ifa;
3272 } 3271 }
3273 3272
3274 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
3275 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3273 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
3276 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3274 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3277 if (err < 0) { 3275 if (err < 0) {
3278 err = -EMSGSIZE; 3276 kfree_skb(skb);
3279 goto out_free; 3277 goto errout_ifa;
3280 } 3278 }
3281 3279
3282 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); 3280 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
3283out: 3281errout_ifa:
3284 in6_ifa_put(ifa); 3282 in6_ifa_put(ifa);
3283errout:
3285 return err; 3284 return err;
3286out_free:
3287 kfree_skb(skb);
3288 goto out;
3289} 3285}
3290 3286
3291static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) 3287static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)