aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-11-14 22:53:58 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:44 -0500
commit04561c1fe7b067a8250e6caaf168256783580c4c (patch)
tree482135e96087cb7c5c81a6a799d409a80f80fb41 /net/ipv6/addrconf.c
parenta928630a2ffeaf6aa9a6b78456935b6ab1be3066 (diff)
[IPv6] iflink: Convert IPv6's RTM_GETLINK to use the new netlink api
By replacing the current method of exporting the device configuration which included allocating a temporary buffer, copying ipv6_devconf into it and copying that buffer into the message with a method that uses nla_reserve() allowing to copy the device configuration directly into the skb data buffer, a GFP_ATOMIC allocation could be removed. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c79
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:
3360static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, 3360static 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)
3409static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 3411static 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
3467nlmsg_failure: 3465nla_put_failure:
3468rtattr_failure: 3466 return nlmsg_cancel(skb, nlh);
3469 kfree(array);
3470 skb_trim(skb, b - skb->data);
3471 return -1;
3472} 3467}
3473 3468
3474static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 3469static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)