aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/devinet.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 6b297c8697e6..309640e9ede1 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -430,34 +430,48 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix,
430 430
431static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 431static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
432{ 432{
433 struct rtattr **rta = arg; 433 struct nlattr *tb[IFA_MAX+1];
434 struct in_device *in_dev; 434 struct in_device *in_dev;
435 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 435 struct ifaddrmsg *ifm;
436 struct in_ifaddr *ifa, **ifap; 436 struct in_ifaddr *ifa, **ifap;
437 int err = -EINVAL;
437 438
438 ASSERT_RTNL(); 439 ASSERT_RTNL();
439 440
440 if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) 441 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy);
441 goto out; 442 if (err < 0)
443 goto errout;
444
445 ifm = nlmsg_data(nlh);
446 in_dev = inetdev_by_index(ifm->ifa_index);
447 if (in_dev == NULL) {
448 err = -ENODEV;
449 goto errout;
450 }
451
442 __in_dev_put(in_dev); 452 __in_dev_put(in_dev);
443 453
444 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; 454 for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
445 ifap = &ifa->ifa_next) { 455 ifap = &ifa->ifa_next) {
446 if ((rta[IFA_LOCAL - 1] && 456 if (tb[IFA_LOCAL] &&
447 memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), 457 ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL]))
448 &ifa->ifa_local, 4)) ||
449 (rta[IFA_LABEL - 1] &&
450 rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) ||
451 (rta[IFA_ADDRESS - 1] &&
452 (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
453 !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]),
454 ifa))))
455 continue; 458 continue;
459
460 if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
461 continue;
462
463 if (tb[IFA_ADDRESS] &&
464 (ifm->ifa_prefixlen != ifa->ifa_prefixlen ||
465 !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa)))
466 continue;
467
456 inet_del_ifa(in_dev, ifap, 1); 468 inet_del_ifa(in_dev, ifap, 1);
457 return 0; 469 return 0;
458 } 470 }
459out: 471
460 return -EADDRNOTAVAIL; 472 err = -EADDRNOTAVAIL;
473errout:
474 return err;
461} 475}
462 476
463static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) 477static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh)