diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 79 |
1 files changed, 37 insertions, 42 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 967ea320a9ca..46cd941d296f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3360,6 +3360,8 @@ errout: | |||
3360 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | 3360 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, |
3361 | __s32 *array, int bytes) | 3361 | __s32 *array, int bytes) |
3362 | { | 3362 | { |
3363 | BUG_ON(bytes < (DEVCONF_MAX * 4)); | ||
3364 | |||
3363 | memset(array, 0, bytes); | 3365 | memset(array, 0, bytes); |
3364 | array[DEVCONF_FORWARDING] = cnf->forwarding; | 3366 | array[DEVCONF_FORWARDING] = cnf->forwarding; |
3365 | array[DEVCONF_HOPLIMIT] = cnf->hop_limit; | 3367 | array[DEVCONF_HOPLIMIT] = cnf->hop_limit; |
@@ -3409,66 +3411,59 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3409 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3411 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
3410 | u32 pid, u32 seq, int event, unsigned int flags) | 3412 | u32 pid, u32 seq, int event, unsigned int flags) |
3411 | { | 3413 | { |
3412 | struct net_device *dev = idev->dev; | 3414 | struct net_device *dev = idev->dev; |
3413 | __s32 *array = NULL; | 3415 | struct nlattr *conf; |
3414 | struct ifinfomsg *r; | 3416 | struct ifinfomsg *hdr; |
3415 | struct nlmsghdr *nlh; | 3417 | struct nlmsghdr *nlh; |
3416 | unsigned char *b = skb->tail; | 3418 | void *protoinfo; |
3417 | struct rtattr *subattr; | 3419 | struct ifla_cacheinfo ci; |
3418 | __u32 mtu = dev->mtu; | ||
3419 | struct ifla_cacheinfo ci; | ||
3420 | 3420 | ||
3421 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); | 3421 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); |
3422 | r = NLMSG_DATA(nlh); | 3422 | if (nlh == NULL) |
3423 | r->ifi_family = AF_INET6; | 3423 | return -ENOBUFS; |
3424 | r->__ifi_pad = 0; | 3424 | |
3425 | r->ifi_type = dev->type; | 3425 | hdr = nlmsg_data(nlh); |
3426 | r->ifi_index = dev->ifindex; | 3426 | hdr->ifi_family = AF_INET6; |
3427 | r->ifi_flags = dev_get_flags(dev); | 3427 | hdr->__ifi_pad = 0; |
3428 | r->ifi_change = 0; | 3428 | hdr->ifi_type = dev->type; |
3429 | hdr->ifi_index = dev->ifindex; | ||
3430 | hdr->ifi_flags = dev_get_flags(dev); | ||
3431 | hdr->ifi_change = 0; | ||
3429 | 3432 | ||
3430 | RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); | 3433 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); |
3431 | 3434 | ||
3432 | if (dev->addr_len) | 3435 | if (dev->addr_len) |
3433 | RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); | 3436 | NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); |
3434 | 3437 | ||
3435 | RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); | 3438 | NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); |
3436 | if (dev->ifindex != dev->iflink) | 3439 | if (dev->ifindex != dev->iflink) |
3437 | RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); | 3440 | NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); |
3438 | |||
3439 | subattr = (struct rtattr*)skb->tail; | ||
3440 | 3441 | ||
3441 | RTA_PUT(skb, IFLA_PROTINFO, 0, NULL); | 3442 | protoinfo = nla_nest_start(skb, IFLA_PROTINFO); |
3443 | if (protoinfo == NULL) | ||
3444 | goto nla_put_failure; | ||
3442 | 3445 | ||
3443 | /* return the device flags */ | 3446 | NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags); |
3444 | RTA_PUT(skb, IFLA_INET6_FLAGS, sizeof(__u32), &idev->if_flags); | ||
3445 | 3447 | ||
3446 | /* return interface cacheinfo */ | ||
3447 | ci.max_reasm_len = IPV6_MAXPLEN; | 3448 | ci.max_reasm_len = IPV6_MAXPLEN; |
3448 | ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100 | 3449 | ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100 |
3449 | + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); | 3450 | + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); |
3450 | ci.reachable_time = idev->nd_parms->reachable_time; | 3451 | ci.reachable_time = idev->nd_parms->reachable_time; |
3451 | ci.retrans_time = idev->nd_parms->retrans_time; | 3452 | ci.retrans_time = idev->nd_parms->retrans_time; |
3452 | RTA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); | 3453 | NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); |
3453 | 3454 | ||
3454 | /* return the device sysctl params */ | 3455 | conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); |
3455 | if ((array = kmalloc(DEVCONF_MAX * sizeof(*array), GFP_ATOMIC)) == NULL) | 3456 | if (conf == NULL) |
3456 | goto rtattr_failure; | 3457 | goto nla_put_failure; |
3457 | ipv6_store_devconf(&idev->cnf, array, DEVCONF_MAX * sizeof(*array)); | 3458 | ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf)); |
3458 | RTA_PUT(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(*array), array); | ||
3459 | 3459 | ||
3460 | /* XXX - Statistics/MC not implemented */ | 3460 | /* XXX - Statistics/MC not implemented */ |
3461 | subattr->rta_len = skb->tail - (u8*)subattr; | ||
3462 | 3461 | ||
3463 | nlh->nlmsg_len = skb->tail - b; | 3462 | nla_nest_end(skb, protoinfo); |
3464 | kfree(array); | 3463 | return nlmsg_end(skb, nlh); |
3465 | return skb->len; | ||
3466 | 3464 | ||
3467 | nlmsg_failure: | 3465 | nla_put_failure: |
3468 | rtattr_failure: | 3466 | return nlmsg_cancel(skb, nlh); |
3469 | kfree(array); | ||
3470 | skb_trim(skb, b - skb->data); | ||
3471 | return -1; | ||
3472 | } | 3467 | } |
3473 | 3468 | ||
3474 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 3469 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |