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.c190
1 files changed, 88 insertions, 102 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index b312a5f7a759..a5e8d207a51b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -232,7 +232,7 @@ static inline unsigned ipv6_addr_scope2type(unsigned scope)
232 232
233int __ipv6_addr_type(const struct in6_addr *addr) 233int __ipv6_addr_type(const struct in6_addr *addr)
234{ 234{
235 u32 st; 235 __be32 st;
236 236
237 st = addr->s6_addr32[0]; 237 st = addr->s6_addr32[0];
238 238
@@ -1164,7 +1164,7 @@ record_it:
1164int ipv6_get_saddr(struct dst_entry *dst, 1164int ipv6_get_saddr(struct dst_entry *dst,
1165 struct in6_addr *daddr, struct in6_addr *saddr) 1165 struct in6_addr *daddr, struct in6_addr *saddr)
1166{ 1166{
1167 return ipv6_dev_get_saddr(dst ? ((struct rt6_info *)dst)->rt6i_idev->dev : NULL, daddr, saddr); 1167 return ipv6_dev_get_saddr(dst ? ip6_dst_idev(dst)->dev : NULL, daddr, saddr);
1168} 1168}
1169 1169
1170 1170
@@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope)
3098 3098
3099static inline int inet6_ifaddr_msgsize(void) 3099static inline int inet6_ifaddr_msgsize(void)
3100{ 3100{
3101 return nlmsg_total_size(sizeof(struct ifaddrmsg) + 3101 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
3102 nla_total_size(16) + 3102 + nla_total_size(16) /* IFA_ADDRESS */
3103 nla_total_size(sizeof(struct ifa_cacheinfo)) + 3103 + nla_total_size(sizeof(struct ifa_cacheinfo));
3104 128);
3105} 3104}
3106 3105
3107static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3106static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3329,10 +3328,8 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
3329 3328
3330 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3329 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
3331 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3330 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3332 if (err < 0) { 3331 /* failure implies BUG in inet6_ifaddr_msgsize() */
3333 kfree_skb(skb); 3332 BUG_ON(err < 0);
3334 goto errout_ifa;
3335 }
3336 3333
3337 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); 3334 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
3338errout_ifa: 3335errout_ifa:
@@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
3351 goto errout; 3348 goto errout;
3352 3349
3353 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); 3350 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
3354 if (err < 0) { 3351 /* failure implies BUG in inet6_ifaddr_msgsize() */
3355 kfree_skb(skb); 3352 BUG_ON(err < 0);
3356 goto errout;
3357 }
3358 3353
3359 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3354 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3360errout: 3355errout:
@@ -3365,6 +3360,8 @@ errout:
3365static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, 3360static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
3366 __s32 *array, int bytes) 3361 __s32 *array, int bytes)
3367{ 3362{
3363 BUG_ON(bytes < (DEVCONF_MAX * 4));
3364
3368 memset(array, 0, bytes); 3365 memset(array, 0, bytes);
3369 array[DEVCONF_FORWARDING] = cnf->forwarding; 3366 array[DEVCONF_FORWARDING] = cnf->forwarding;
3370 array[DEVCONF_HOPLIMIT] = cnf->hop_limit; 3367 array[DEVCONF_HOPLIMIT] = cnf->hop_limit;
@@ -3397,80 +3394,76 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
3397 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; 3394 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
3398} 3395}
3399 3396
3400/* Maximum length of ifinfomsg attributes */ 3397static inline size_t inet6_if_nlmsg_size(void)
3401#define INET6_IFINFO_RTA_SPACE \ 3398{
3402 RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ 3399 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
3403 RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ 3400 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
3404 RTA_SPACE(sizeof(u32)) /* MTU */ + \ 3401 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
3405 RTA_SPACE(sizeof(int)) /* LINK */ + \ 3402 + nla_total_size(4) /* IFLA_MTU */
3406 RTA_SPACE(0) /* PROTINFO */ + \ 3403 + nla_total_size(4) /* IFLA_LINK */
3407 RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ 3404 + nla_total_size( /* IFLA_PROTINFO */
3408 RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ 3405 nla_total_size(4) /* IFLA_INET6_FLAGS */
3409 RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ 3406 + nla_total_size(sizeof(struct ifla_cacheinfo))
3407 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
3408 );
3409}
3410 3410
3411static 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,
3412 u32 pid, u32 seq, int event, unsigned int flags) 3412 u32 pid, u32 seq, int event, unsigned int flags)
3413{ 3413{
3414 struct net_device *dev = idev->dev; 3414 struct net_device *dev = idev->dev;
3415 __s32 *array = NULL; 3415 struct nlattr *conf;
3416 struct ifinfomsg *r; 3416 struct ifinfomsg *hdr;
3417 struct nlmsghdr *nlh; 3417 struct nlmsghdr *nlh;
3418 unsigned char *b = skb->tail; 3418 void *protoinfo;
3419 struct rtattr *subattr; 3419 struct ifla_cacheinfo ci;
3420 __u32 mtu = dev->mtu; 3420
3421 struct ifla_cacheinfo ci; 3421 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
3422 3422 if (nlh == NULL)
3423 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); 3423 return -ENOBUFS;
3424 r = NLMSG_DATA(nlh); 3424
3425 r->ifi_family = AF_INET6; 3425 hdr = nlmsg_data(nlh);
3426 r->__ifi_pad = 0; 3426 hdr->ifi_family = AF_INET6;
3427 r->ifi_type = dev->type; 3427 hdr->__ifi_pad = 0;
3428 r->ifi_index = dev->ifindex; 3428 hdr->ifi_type = dev->type;
3429 r->ifi_flags = dev_get_flags(dev); 3429 hdr->ifi_index = dev->ifindex;
3430 r->ifi_change = 0; 3430 hdr->ifi_flags = dev_get_flags(dev);
3431 3431 hdr->ifi_change = 0;
3432 RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); 3432
3433 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
3433 3434
3434 if (dev->addr_len) 3435 if (dev->addr_len)
3435 RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); 3436 NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
3436 3437
3437 RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); 3438 NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
3438 if (dev->ifindex != dev->iflink) 3439 if (dev->ifindex != dev->iflink)
3439 RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); 3440 NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
3440
3441 subattr = (struct rtattr*)skb->tail;
3442 3441
3443 RTA_PUT(skb, IFLA_PROTINFO, 0, NULL); 3442 protoinfo = nla_nest_start(skb, IFLA_PROTINFO);
3443 if (protoinfo == NULL)
3444 goto nla_put_failure;
3444 3445
3445 /* return the device flags */ 3446 NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
3446 RTA_PUT(skb, IFLA_INET6_FLAGS, sizeof(__u32), &idev->if_flags);
3447 3447
3448 /* return interface cacheinfo */
3449 ci.max_reasm_len = IPV6_MAXPLEN; 3448 ci.max_reasm_len = IPV6_MAXPLEN;
3450 ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100 3449 ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
3451 + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); 3450 + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
3452 ci.reachable_time = idev->nd_parms->reachable_time; 3451 ci.reachable_time = idev->nd_parms->reachable_time;
3453 ci.retrans_time = idev->nd_parms->retrans_time; 3452 ci.retrans_time = idev->nd_parms->retrans_time;
3454 RTA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); 3453 NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
3455 3454
3456 /* return the device sysctl params */ 3455 conf = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
3457 if ((array = kmalloc(DEVCONF_MAX * sizeof(*array), GFP_ATOMIC)) == NULL) 3456 if (conf == NULL)
3458 goto rtattr_failure; 3457 goto nla_put_failure;
3459 ipv6_store_devconf(&idev->cnf, array, DEVCONF_MAX * sizeof(*array)); 3458 ipv6_store_devconf(&idev->cnf, nla_data(conf), nla_len(conf));
3460 RTA_PUT(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(*array), array);
3461 3459
3462 /* XXX - Statistics/MC not implemented */ 3460 /* XXX - Statistics/MC not implemented */
3463 subattr->rta_len = skb->tail - (u8*)subattr;
3464 3461
3465 nlh->nlmsg_len = skb->tail - b; 3462 nla_nest_end(skb, protoinfo);
3466 kfree(array); 3463 return nlmsg_end(skb, nlh);
3467 return skb->len;
3468 3464
3469nlmsg_failure: 3465nla_put_failure:
3470rtattr_failure: 3466 return nlmsg_cancel(skb, nlh);
3471 kfree(array);
3472 skb_trim(skb, b - skb->data);
3473 return -1;
3474} 3467}
3475 3468
3476static 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)
@@ -3501,18 +3494,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
3501void inet6_ifinfo_notify(int event, struct inet6_dev *idev) 3494void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
3502{ 3495{
3503 struct sk_buff *skb; 3496 struct sk_buff *skb;
3504 int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
3505 int err = -ENOBUFS; 3497 int err = -ENOBUFS;
3506 3498
3507 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 3499 skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
3508 if (skb == NULL) 3500 if (skb == NULL)
3509 goto errout; 3501 goto errout;
3510 3502
3511 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); 3503 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
3512 if (err < 0) { 3504 /* failure implies BUG in inet6_if_nlmsg_size() */
3513 kfree_skb(skb); 3505 BUG_ON(err < 0);
3514 goto errout;
3515 }
3516 3506
3517 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3507 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3518errout: 3508errout:
@@ -3520,22 +3510,26 @@ errout:
3520 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); 3510 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
3521} 3511}
3522 3512
3523/* Maximum length of prefix_cacheinfo attributes */ 3513static inline size_t inet6_prefix_nlmsg_size(void)
3524#define INET6_PREFIX_RTA_SPACE \ 3514{
3525 RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ 3515 return NLMSG_ALIGN(sizeof(struct prefixmsg))
3526 RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ 3516 + nla_total_size(sizeof(struct in6_addr))
3517 + nla_total_size(sizeof(struct prefix_cacheinfo));
3518}
3527 3519
3528static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, 3520static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
3529 struct prefix_info *pinfo, u32 pid, u32 seq, 3521 struct prefix_info *pinfo, u32 pid, u32 seq,
3530 int event, unsigned int flags) 3522 int event, unsigned int flags)
3531{ 3523{
3532 struct prefixmsg *pmsg; 3524 struct prefixmsg *pmsg;
3533 struct nlmsghdr *nlh; 3525 struct nlmsghdr *nlh;
3534 unsigned char *b = skb->tail;
3535 struct prefix_cacheinfo ci; 3526 struct prefix_cacheinfo ci;
3536 3527
3537 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*pmsg), flags); 3528 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
3538 pmsg = NLMSG_DATA(nlh); 3529 if (nlh == NULL)
3530 return -ENOBUFS;
3531
3532 pmsg = nlmsg_data(nlh);
3539 pmsg->prefix_family = AF_INET6; 3533 pmsg->prefix_family = AF_INET6;
3540 pmsg->prefix_pad1 = 0; 3534 pmsg->prefix_pad1 = 0;
3541 pmsg->prefix_pad2 = 0; 3535 pmsg->prefix_pad2 = 0;
@@ -3543,44 +3537,37 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
3543 pmsg->prefix_len = pinfo->prefix_len; 3537 pmsg->prefix_len = pinfo->prefix_len;
3544 pmsg->prefix_type = pinfo->type; 3538 pmsg->prefix_type = pinfo->type;
3545 pmsg->prefix_pad3 = 0; 3539 pmsg->prefix_pad3 = 0;
3546
3547 pmsg->prefix_flags = 0; 3540 pmsg->prefix_flags = 0;
3548 if (pinfo->onlink) 3541 if (pinfo->onlink)
3549 pmsg->prefix_flags |= IF_PREFIX_ONLINK; 3542 pmsg->prefix_flags |= IF_PREFIX_ONLINK;
3550 if (pinfo->autoconf) 3543 if (pinfo->autoconf)
3551 pmsg->prefix_flags |= IF_PREFIX_AUTOCONF; 3544 pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
3552 3545
3553 RTA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix); 3546 NLA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
3554 3547
3555 ci.preferred_time = ntohl(pinfo->prefered); 3548 ci.preferred_time = ntohl(pinfo->prefered);
3556 ci.valid_time = ntohl(pinfo->valid); 3549 ci.valid_time = ntohl(pinfo->valid);
3557 RTA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci); 3550 NLA_PUT(skb, PREFIX_CACHEINFO, sizeof(ci), &ci);
3558 3551
3559 nlh->nlmsg_len = skb->tail - b; 3552 return nlmsg_end(skb, nlh);
3560 return skb->len;
3561 3553
3562nlmsg_failure: 3554nla_put_failure:
3563rtattr_failure: 3555 return nlmsg_cancel(skb, nlh);
3564 skb_trim(skb, b - skb->data);
3565 return -1;
3566} 3556}
3567 3557
3568static void inet6_prefix_notify(int event, struct inet6_dev *idev, 3558static void inet6_prefix_notify(int event, struct inet6_dev *idev,
3569 struct prefix_info *pinfo) 3559 struct prefix_info *pinfo)
3570{ 3560{
3571 struct sk_buff *skb; 3561 struct sk_buff *skb;
3572 int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
3573 int err = -ENOBUFS; 3562 int err = -ENOBUFS;
3574 3563
3575 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 3564 skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
3576 if (skb == NULL) 3565 if (skb == NULL)
3577 goto errout; 3566 goto errout;
3578 3567
3579 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); 3568 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
3580 if (err < 0) { 3569 /* failure implies BUG in inet6_prefix_nlmsg_size() */
3581 kfree_skb(skb); 3570 BUG_ON(err < 0);
3582 goto errout;
3583 }
3584 3571
3585 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); 3572 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
3586errout: 3573errout:
@@ -3982,10 +3969,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
3982 struct addrconf_sysctl_table *t; 3969 struct addrconf_sysctl_table *t;
3983 char *dev_name = NULL; 3970 char *dev_name = NULL;
3984 3971
3985 t = kmalloc(sizeof(*t), GFP_KERNEL); 3972 t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL);
3986 if (t == NULL) 3973 if (t == NULL)
3987 return; 3974 return;
3988 memcpy(t, &addrconf_sysctl, sizeof(*t));
3989 for (i=0; t->addrconf_vars[i].data; i++) { 3975 for (i=0; t->addrconf_vars[i].data; i++) {
3990 t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; 3976 t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf;
3991 t->addrconf_vars[i].de = NULL; 3977 t->addrconf_vars[i].de = NULL;