diff options
Diffstat (limited to 'net/ipv6')
44 files changed, 1592 insertions, 991 deletions
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 6e48f52e197c..deb4101a2a81 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -196,10 +196,3 @@ config IPV6_SUBTREES | |||
196 | 196 | ||
197 | If unsure, say N. | 197 | If unsure, say N. |
198 | 198 | ||
199 | config IPV6_ROUTE_FWMARK | ||
200 | bool "IPv6: use netfilter MARK value as routing key" | ||
201 | depends on IPV6_MULTIPLE_TABLES && NETFILTER | ||
202 | ---help--- | ||
203 | If you say Y here, you will be able to specify different routes for | ||
204 | packets with different mark values (see iptables(8), MARK target). | ||
205 | |||
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index addcc011bc01..8bacda109b7f 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -5,8 +5,8 @@ | |||
5 | obj-$(CONFIG_IPV6) += ipv6.o | 5 | obj-$(CONFIG_IPV6) += ipv6.o |
6 | 6 | ||
7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ | 7 | ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ |
8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o raw.o \ | 8 | route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ |
9 | protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ | 9 | raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ |
10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ | 10 | exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ |
11 | ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o | 11 | ip6_flowlabel.o ipv6_syms.o inet6_connection_sock.o |
12 | 12 | ||
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 | ||
233 | int __ipv6_addr_type(const struct in6_addr *addr) | 233 | int __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: | |||
1164 | int ipv6_get_saddr(struct dst_entry *dst, | 1164 | int 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 | ||
3099 | static inline int inet6_ifaddr_msgsize(void) | 3099 | static 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 | ||
3107 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 3106 | static 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); |
3338 | errout_ifa: | 3335 | errout_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); |
3360 | errout: | 3355 | errout: |
@@ -3365,6 +3360,8 @@ errout: | |||
3365 | static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, | 3360 | static 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 */ | 3397 | static 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 | ||
3411 | 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, |
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 | ||
3469 | nlmsg_failure: | 3465 | nla_put_failure: |
3470 | rtattr_failure: | 3466 | return nlmsg_cancel(skb, nlh); |
3471 | kfree(array); | ||
3472 | skb_trim(skb, b - skb->data); | ||
3473 | return -1; | ||
3474 | } | 3467 | } |
3475 | 3468 | ||
3476 | 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) |
@@ -3501,18 +3494,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
3501 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3494 | void 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); |
3518 | errout: | 3508 | errout: |
@@ -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 */ | 3513 | static 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 | ||
3528 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | 3520 | static 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 | ||
3562 | nlmsg_failure: | 3554 | nla_put_failure: |
3563 | rtattr_failure: | 3555 | return nlmsg_cancel(skb, nlh); |
3564 | skb_trim(skb, b - skb->data); | ||
3565 | return -1; | ||
3566 | } | 3556 | } |
3567 | 3557 | ||
3568 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 3558 | static 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); |
3586 | errout: | 3573 | errout: |
@@ -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; |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 858cae29581c..87c8f54872b7 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <net/ip.h> | 49 | #include <net/ip.h> |
50 | #include <net/ipv6.h> | 50 | #include <net/ipv6.h> |
51 | #include <net/udp.h> | 51 | #include <net/udp.h> |
52 | #include <net/udplite.h> | ||
52 | #include <net/tcp.h> | 53 | #include <net/tcp.h> |
53 | #include <net/ipip.h> | 54 | #include <net/ipip.h> |
54 | #include <net/protocol.h> | 55 | #include <net/protocol.h> |
@@ -221,7 +222,7 @@ lookup_protocol: | |||
221 | * the user to assign a number at socket | 222 | * the user to assign a number at socket |
222 | * creation time automatically shares. | 223 | * creation time automatically shares. |
223 | */ | 224 | */ |
224 | inet->sport = ntohs(inet->num); | 225 | inet->sport = htons(inet->num); |
225 | sk->sk_prot->hash(sk); | 226 | sk->sk_prot->hash(sk); |
226 | } | 227 | } |
227 | if (sk->sk_prot->init) { | 228 | if (sk->sk_prot->init) { |
@@ -341,7 +342,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
341 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; | 342 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; |
342 | if (snum) | 343 | if (snum) |
343 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 344 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; |
344 | inet->sport = ntohs(inet->num); | 345 | inet->sport = htons(inet->num); |
345 | inet->dport = 0; | 346 | inet->dport = 0; |
346 | inet->daddr = 0; | 347 | inet->daddr = 0; |
347 | out: | 348 | out: |
@@ -678,7 +679,7 @@ int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
678 | if (np->rxopt.all) { | 679 | if (np->rxopt.all) { |
679 | if ((opt->hop && (np->rxopt.bits.hopopts || | 680 | if ((opt->hop && (np->rxopt.bits.hopopts || |
680 | np->rxopt.bits.ohopopts)) || | 681 | np->rxopt.bits.ohopopts)) || |
681 | ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && | 682 | ((IPV6_FLOWINFO_MASK & *(__be32*)skb->nh.raw) && |
682 | np->rxopt.bits.rxflow) || | 683 | np->rxopt.bits.rxflow) || |
683 | (opt->srcrt && (np->rxopt.bits.srcrt || | 684 | (opt->srcrt && (np->rxopt.bits.srcrt || |
684 | np->rxopt.bits.osrcrt)) || | 685 | np->rxopt.bits.osrcrt)) || |
@@ -737,8 +738,13 @@ static int __init init_ipv6_mibs(void) | |||
737 | if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), | 738 | if (snmp6_mib_init((void **)udp_stats_in6, sizeof (struct udp_mib), |
738 | __alignof__(struct udp_mib)) < 0) | 739 | __alignof__(struct udp_mib)) < 0) |
739 | goto err_udp_mib; | 740 | goto err_udp_mib; |
741 | if (snmp6_mib_init((void **)udplite_stats_in6, sizeof (struct udp_mib), | ||
742 | __alignof__(struct udp_mib)) < 0) | ||
743 | goto err_udplite_mib; | ||
740 | return 0; | 744 | return 0; |
741 | 745 | ||
746 | err_udplite_mib: | ||
747 | snmp6_mib_free((void **)udp_stats_in6); | ||
742 | err_udp_mib: | 748 | err_udp_mib: |
743 | snmp6_mib_free((void **)icmpv6_statistics); | 749 | snmp6_mib_free((void **)icmpv6_statistics); |
744 | err_icmp_mib: | 750 | err_icmp_mib: |
@@ -753,6 +759,7 @@ static void cleanup_ipv6_mibs(void) | |||
753 | snmp6_mib_free((void **)ipv6_statistics); | 759 | snmp6_mib_free((void **)ipv6_statistics); |
754 | snmp6_mib_free((void **)icmpv6_statistics); | 760 | snmp6_mib_free((void **)icmpv6_statistics); |
755 | snmp6_mib_free((void **)udp_stats_in6); | 761 | snmp6_mib_free((void **)udp_stats_in6); |
762 | snmp6_mib_free((void **)udplite_stats_in6); | ||
756 | } | 763 | } |
757 | 764 | ||
758 | static int __init inet6_init(void) | 765 | static int __init inet6_init(void) |
@@ -780,10 +787,14 @@ static int __init inet6_init(void) | |||
780 | if (err) | 787 | if (err) |
781 | goto out_unregister_tcp_proto; | 788 | goto out_unregister_tcp_proto; |
782 | 789 | ||
783 | err = proto_register(&rawv6_prot, 1); | 790 | err = proto_register(&udplitev6_prot, 1); |
784 | if (err) | 791 | if (err) |
785 | goto out_unregister_udp_proto; | 792 | goto out_unregister_udp_proto; |
786 | 793 | ||
794 | err = proto_register(&rawv6_prot, 1); | ||
795 | if (err) | ||
796 | goto out_unregister_udplite_proto; | ||
797 | |||
787 | 798 | ||
788 | /* Register the socket-side information for inet6_create. */ | 799 | /* Register the socket-side information for inet6_create. */ |
789 | for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) | 800 | for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r) |
@@ -837,6 +848,8 @@ static int __init inet6_init(void) | |||
837 | goto proc_tcp6_fail; | 848 | goto proc_tcp6_fail; |
838 | if (udp6_proc_init()) | 849 | if (udp6_proc_init()) |
839 | goto proc_udp6_fail; | 850 | goto proc_udp6_fail; |
851 | if (udplite6_proc_init()) | ||
852 | goto proc_udplite6_fail; | ||
840 | if (ipv6_misc_proc_init()) | 853 | if (ipv6_misc_proc_init()) |
841 | goto proc_misc6_fail; | 854 | goto proc_misc6_fail; |
842 | 855 | ||
@@ -862,6 +875,7 @@ static int __init inet6_init(void) | |||
862 | 875 | ||
863 | /* Init v6 transport protocols. */ | 876 | /* Init v6 transport protocols. */ |
864 | udpv6_init(); | 877 | udpv6_init(); |
878 | udplitev6_init(); | ||
865 | tcpv6_init(); | 879 | tcpv6_init(); |
866 | 880 | ||
867 | ipv6_packet_init(); | 881 | ipv6_packet_init(); |
@@ -879,6 +893,8 @@ proc_if6_fail: | |||
879 | proc_anycast6_fail: | 893 | proc_anycast6_fail: |
880 | ipv6_misc_proc_exit(); | 894 | ipv6_misc_proc_exit(); |
881 | proc_misc6_fail: | 895 | proc_misc6_fail: |
896 | udplite6_proc_exit(); | ||
897 | proc_udplite6_fail: | ||
882 | udp6_proc_exit(); | 898 | udp6_proc_exit(); |
883 | proc_udp6_fail: | 899 | proc_udp6_fail: |
884 | tcp6_proc_exit(); | 900 | tcp6_proc_exit(); |
@@ -902,6 +918,8 @@ out_unregister_sock: | |||
902 | sock_unregister(PF_INET6); | 918 | sock_unregister(PF_INET6); |
903 | out_unregister_raw_proto: | 919 | out_unregister_raw_proto: |
904 | proto_unregister(&rawv6_prot); | 920 | proto_unregister(&rawv6_prot); |
921 | out_unregister_udplite_proto: | ||
922 | proto_unregister(&udplitev6_prot); | ||
905 | out_unregister_udp_proto: | 923 | out_unregister_udp_proto: |
906 | proto_unregister(&udpv6_prot); | 924 | proto_unregister(&udpv6_prot); |
907 | out_unregister_tcp_proto: | 925 | out_unregister_tcp_proto: |
@@ -919,6 +937,7 @@ static void __exit inet6_exit(void) | |||
919 | ac6_proc_exit(); | 937 | ac6_proc_exit(); |
920 | ipv6_misc_proc_exit(); | 938 | ipv6_misc_proc_exit(); |
921 | udp6_proc_exit(); | 939 | udp6_proc_exit(); |
940 | udplite6_proc_exit(); | ||
922 | tcp6_proc_exit(); | 941 | tcp6_proc_exit(); |
923 | raw6_proc_exit(); | 942 | raw6_proc_exit(); |
924 | #endif | 943 | #endif |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index b0d83e8e4252..12c5a4dec09e 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -354,10 +354,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
354 | if (!pskb_may_pull(skb, ah_hlen)) | 354 | if (!pskb_may_pull(skb, ah_hlen)) |
355 | goto out; | 355 | goto out; |
356 | 356 | ||
357 | tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); | 357 | tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); |
358 | if (!tmp_hdr) | 358 | if (!tmp_hdr) |
359 | goto out; | 359 | goto out; |
360 | memcpy(tmp_hdr, skb->nh.raw, hdr_len); | ||
361 | if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) | 360 | if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) |
362 | goto free_out; | 361 | goto free_out; |
363 | skb->nh.ipv6h->priority = 0; | 362 | skb->nh.ipv6h->priority = 0; |
@@ -397,7 +396,7 @@ out: | |||
397 | } | 396 | } |
398 | 397 | ||
399 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 398 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
400 | int type, int code, int offset, __u32 info) | 399 | int type, int code, int offset, __be32 info) |
401 | { | 400 | { |
402 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 401 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
403 | struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset); | 402 | struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset); |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 7206747022fc..5c94fea90e97 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -207,7 +207,7 @@ out: | |||
207 | } | 207 | } |
208 | 208 | ||
209 | void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, | 209 | void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, |
210 | u16 port, u32 info, u8 *payload) | 210 | __be16 port, u32 info, u8 *payload) |
211 | { | 211 | { |
212 | struct ipv6_pinfo *np = inet6_sk(sk); | 212 | struct ipv6_pinfo *np = inet6_sk(sk); |
213 | struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; | 213 | struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; |
@@ -318,13 +318,13 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) | |||
318 | ipv6_addr_copy(&sin->sin6_addr, | 318 | ipv6_addr_copy(&sin->sin6_addr, |
319 | (struct in6_addr *)(skb->nh.raw + serr->addr_offset)); | 319 | (struct in6_addr *)(skb->nh.raw + serr->addr_offset)); |
320 | if (np->sndflow) | 320 | if (np->sndflow) |
321 | sin->sin6_flowinfo = *(u32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; | 321 | sin->sin6_flowinfo = *(__be32*)(skb->nh.raw + serr->addr_offset - 24) & IPV6_FLOWINFO_MASK; |
322 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 322 | if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
323 | sin->sin6_scope_id = IP6CB(skb)->iif; | 323 | sin->sin6_scope_id = IP6CB(skb)->iif; |
324 | } else { | 324 | } else { |
325 | ipv6_addr_set(&sin->sin6_addr, 0, 0, | 325 | ipv6_addr_set(&sin->sin6_addr, 0, 0, |
326 | htonl(0xffff), | 326 | htonl(0xffff), |
327 | *(u32*)(skb->nh.raw + serr->addr_offset)); | 327 | *(__be32*)(skb->nh.raw + serr->addr_offset)); |
328 | } | 328 | } |
329 | } | 329 | } |
330 | 330 | ||
@@ -397,12 +397,12 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
397 | } | 397 | } |
398 | 398 | ||
399 | if (np->rxopt.bits.rxtclass) { | 399 | if (np->rxopt.bits.rxtclass) { |
400 | int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff; | 400 | int tclass = (ntohl(*(__be32 *)skb->nh.ipv6h) >> 20) & 0xff; |
401 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); | 401 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); |
402 | } | 402 | } |
403 | 403 | ||
404 | if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { | 404 | if (np->rxopt.bits.rxflow && (*(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { |
405 | u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK; | 405 | __be32 flowinfo = *(__be32*)skb->nh.raw & IPV6_FLOWINFO_MASK; |
406 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); | 406 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); |
407 | } | 407 | } |
408 | 408 | ||
@@ -560,12 +560,12 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
560 | } | 560 | } |
561 | 561 | ||
562 | if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) { | 562 | if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) { |
563 | if ((fl->fl6_flowlabel^*(u32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { | 563 | if ((fl->fl6_flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) { |
564 | err = -EINVAL; | 564 | err = -EINVAL; |
565 | goto exit_f; | 565 | goto exit_f; |
566 | } | 566 | } |
567 | } | 567 | } |
568 | fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); | 568 | fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg); |
569 | break; | 569 | break; |
570 | 570 | ||
571 | case IPV6_2292HOPOPTS: | 571 | case IPV6_2292HOPOPTS: |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index e78680a9985b..25dcf69cd807 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -256,7 +256,7 @@ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) | |||
256 | } | 256 | } |
257 | 257 | ||
258 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 258 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
259 | int type, int code, int offset, __u32 info) | 259 | int type, int code, int offset, __be32 info) |
260 | { | 260 | { |
261 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 261 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
262 | struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset); | 262 | struct ipv6_esp_hdr *esph = (struct ipv6_esp_hdr*)(skb->data+offset); |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 88c96b10684c..0711f92d6a12 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -284,10 +284,12 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
284 | #ifdef CONFIG_IPV6_MIP6 | 284 | #ifdef CONFIG_IPV6_MIP6 |
285 | __u16 dstbuf; | 285 | __u16 dstbuf; |
286 | #endif | 286 | #endif |
287 | struct dst_entry *dst; | ||
287 | 288 | ||
288 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 289 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
289 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 290 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
290 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 291 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
292 | IPSTATS_MIB_INHDRERRORS); | ||
291 | kfree_skb(skb); | 293 | kfree_skb(skb); |
292 | return -1; | 294 | return -1; |
293 | } | 295 | } |
@@ -298,7 +300,9 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
298 | dstbuf = opt->dst1; | 300 | dstbuf = opt->dst1; |
299 | #endif | 301 | #endif |
300 | 302 | ||
303 | dst = dst_clone(skb->dst); | ||
301 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { | 304 | if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { |
305 | dst_release(dst); | ||
302 | skb = *skbp; | 306 | skb = *skbp; |
303 | skb->h.raw += ((skb->h.raw[1]+1)<<3); | 307 | skb->h.raw += ((skb->h.raw[1]+1)<<3); |
304 | opt = IP6CB(skb); | 308 | opt = IP6CB(skb); |
@@ -310,7 +314,8 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) | |||
310 | return 1; | 314 | return 1; |
311 | } | 315 | } |
312 | 316 | ||
313 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 317 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
318 | dst_release(dst); | ||
314 | return -1; | 319 | return -1; |
315 | } | 320 | } |
316 | 321 | ||
@@ -365,7 +370,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
365 | 370 | ||
366 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || | 371 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || |
367 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { | 372 | !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { |
368 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 373 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
374 | IPSTATS_MIB_INHDRERRORS); | ||
369 | kfree_skb(skb); | 375 | kfree_skb(skb); |
370 | return -1; | 376 | return -1; |
371 | } | 377 | } |
@@ -374,7 +380,8 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) | |||
374 | 380 | ||
375 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || | 381 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr) || |
376 | skb->pkt_type != PACKET_HOST) { | 382 | skb->pkt_type != PACKET_HOST) { |
377 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 383 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
384 | IPSTATS_MIB_INADDRERRORS); | ||
378 | kfree_skb(skb); | 385 | kfree_skb(skb); |
379 | return -1; | 386 | return -1; |
380 | } | 387 | } |
@@ -388,7 +395,8 @@ looped_back: | |||
388 | * processed by own | 395 | * processed by own |
389 | */ | 396 | */ |
390 | if (!addr) { | 397 | if (!addr) { |
391 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 398 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
399 | IPSTATS_MIB_INADDRERRORS); | ||
392 | kfree_skb(skb); | 400 | kfree_skb(skb); |
393 | return -1; | 401 | return -1; |
394 | } | 402 | } |
@@ -410,7 +418,8 @@ looped_back: | |||
410 | switch (hdr->type) { | 418 | switch (hdr->type) { |
411 | case IPV6_SRCRT_TYPE_0: | 419 | case IPV6_SRCRT_TYPE_0: |
412 | if (hdr->hdrlen & 0x01) { | 420 | if (hdr->hdrlen & 0x01) { |
413 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 421 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
422 | IPSTATS_MIB_INHDRERRORS); | ||
414 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); | 423 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); |
415 | return -1; | 424 | return -1; |
416 | } | 425 | } |
@@ -419,14 +428,16 @@ looped_back: | |||
419 | case IPV6_SRCRT_TYPE_2: | 428 | case IPV6_SRCRT_TYPE_2: |
420 | /* Silently discard invalid RTH type 2 */ | 429 | /* Silently discard invalid RTH type 2 */ |
421 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { | 430 | if (hdr->hdrlen != 2 || hdr->segments_left != 1) { |
422 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 431 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
432 | IPSTATS_MIB_INHDRERRORS); | ||
423 | kfree_skb(skb); | 433 | kfree_skb(skb); |
424 | return -1; | 434 | return -1; |
425 | } | 435 | } |
426 | break; | 436 | break; |
427 | #endif | 437 | #endif |
428 | default: | 438 | default: |
429 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 439 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
440 | IPSTATS_MIB_INHDRERRORS); | ||
430 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); | 441 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); |
431 | return -1; | 442 | return -1; |
432 | } | 443 | } |
@@ -439,7 +450,8 @@ looped_back: | |||
439 | n = hdr->hdrlen >> 1; | 450 | n = hdr->hdrlen >> 1; |
440 | 451 | ||
441 | if (hdr->segments_left > n) { | 452 | if (hdr->segments_left > n) { |
442 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 453 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
454 | IPSTATS_MIB_INHDRERRORS); | ||
443 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); | 455 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); |
444 | return -1; | 456 | return -1; |
445 | } | 457 | } |
@@ -449,12 +461,14 @@ looped_back: | |||
449 | */ | 461 | */ |
450 | if (skb_cloned(skb)) { | 462 | if (skb_cloned(skb)) { |
451 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); | 463 | struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); |
452 | kfree_skb(skb); | ||
453 | /* the copy is a forwarded packet */ | 464 | /* the copy is a forwarded packet */ |
454 | if (skb2 == NULL) { | 465 | if (skb2 == NULL) { |
455 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTDISCARDS); | 466 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
467 | IPSTATS_MIB_OUTDISCARDS); | ||
468 | kfree_skb(skb); | ||
456 | return -1; | 469 | return -1; |
457 | } | 470 | } |
471 | kfree_skb(skb); | ||
458 | *skbp = skb = skb2; | 472 | *skbp = skb = skb2; |
459 | opt = IP6CB(skb2); | 473 | opt = IP6CB(skb2); |
460 | hdr = (struct ipv6_rt_hdr *) skb2->h.raw; | 474 | hdr = (struct ipv6_rt_hdr *) skb2->h.raw; |
@@ -475,12 +489,14 @@ looped_back: | |||
475 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, | 489 | if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, |
476 | (xfrm_address_t *)&skb->nh.ipv6h->saddr, | 490 | (xfrm_address_t *)&skb->nh.ipv6h->saddr, |
477 | IPPROTO_ROUTING) < 0) { | 491 | IPPROTO_ROUTING) < 0) { |
478 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 492 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
493 | IPSTATS_MIB_INADDRERRORS); | ||
479 | kfree_skb(skb); | 494 | kfree_skb(skb); |
480 | return -1; | 495 | return -1; |
481 | } | 496 | } |
482 | if (!ipv6_chk_home_addr(addr)) { | 497 | if (!ipv6_chk_home_addr(addr)) { |
483 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 498 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
499 | IPSTATS_MIB_INADDRERRORS); | ||
484 | kfree_skb(skb); | 500 | kfree_skb(skb); |
485 | return -1; | 501 | return -1; |
486 | } | 502 | } |
@@ -491,7 +507,8 @@ looped_back: | |||
491 | } | 507 | } |
492 | 508 | ||
493 | if (ipv6_addr_is_multicast(addr)) { | 509 | if (ipv6_addr_is_multicast(addr)) { |
494 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 510 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
511 | IPSTATS_MIB_INADDRERRORS); | ||
495 | kfree_skb(skb); | 512 | kfree_skb(skb); |
496 | return -1; | 513 | return -1; |
497 | } | 514 | } |
@@ -510,7 +527,8 @@ looped_back: | |||
510 | 527 | ||
511 | if (skb->dst->dev->flags&IFF_LOOPBACK) { | 528 | if (skb->dst->dev->flags&IFF_LOOPBACK) { |
512 | if (skb->nh.ipv6h->hop_limit <= 1) { | 529 | if (skb->nh.ipv6h->hop_limit <= 1) { |
513 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 530 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
531 | IPSTATS_MIB_INHDRERRORS); | ||
514 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 532 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, |
515 | 0, skb->dev); | 533 | 0, skb->dev); |
516 | kfree_skb(skb); | 534 | kfree_skb(skb); |
@@ -632,24 +650,25 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) | |||
632 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { | 650 | if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { |
633 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", | 651 | LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", |
634 | skb->nh.raw[optoff+1]); | 652 | skb->nh.raw[optoff+1]); |
635 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 653 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
654 | IPSTATS_MIB_INHDRERRORS); | ||
636 | goto drop; | 655 | goto drop; |
637 | } | 656 | } |
638 | 657 | ||
639 | pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); | 658 | pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); |
640 | if (pkt_len <= IPV6_MAXPLEN) { | 659 | if (pkt_len <= IPV6_MAXPLEN) { |
641 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 660 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
642 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); | 661 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); |
643 | return 0; | 662 | return 0; |
644 | } | 663 | } |
645 | if (skb->nh.ipv6h->payload_len) { | 664 | if (skb->nh.ipv6h->payload_len) { |
646 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 665 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
647 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); | 666 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff); |
648 | return 0; | 667 | return 0; |
649 | } | 668 | } |
650 | 669 | ||
651 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { | 670 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) { |
652 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); | 671 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS); |
653 | goto drop; | 672 | goto drop; |
654 | } | 673 | } |
655 | 674 | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 315bc1fbec3f..21cbbbddaf4d 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
@@ -77,7 +77,7 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) | |||
77 | if (hp == NULL) | 77 | if (hp == NULL) |
78 | return -1; | 78 | return -1; |
79 | if (nexthdr == NEXTHDR_FRAGMENT) { | 79 | if (nexthdr == NEXTHDR_FRAGMENT) { |
80 | unsigned short _frag_off, *fp; | 80 | __be16 _frag_off, *fp; |
81 | fp = skb_header_pointer(skb, | 81 | fp = skb_header_pointer(skb, |
82 | start+offsetof(struct frag_hdr, | 82 | start+offsetof(struct frag_hdr, |
83 | frag_off), | 83 | frag_off), |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 1896ecb52899..0862809ffcf7 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
@@ -25,10 +25,6 @@ struct fib6_rule | |||
25 | struct fib_rule common; | 25 | struct fib_rule common; |
26 | struct rt6key src; | 26 | struct rt6key src; |
27 | struct rt6key dst; | 27 | struct rt6key dst; |
28 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
29 | u32 fwmark; | ||
30 | u32 fwmask; | ||
31 | #endif | ||
32 | u8 tclass; | 28 | u8 tclass; |
33 | }; | 29 | }; |
34 | 30 | ||
@@ -67,7 +63,7 @@ struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | |||
67 | fib_rule_put(arg.rule); | 63 | fib_rule_put(arg.rule); |
68 | 64 | ||
69 | if (arg.result) | 65 | if (arg.result) |
70 | return (struct dst_entry *) arg.result; | 66 | return arg.result; |
71 | 67 | ||
72 | dst_hold(&ip6_null_entry.u.dst); | 68 | dst_hold(&ip6_null_entry.u.dst); |
73 | return &ip6_null_entry.u.dst; | 69 | return &ip6_null_entry.u.dst; |
@@ -130,22 +126,13 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | |||
130 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) | 126 | if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) |
131 | return 0; | 127 | return 0; |
132 | 128 | ||
133 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
134 | if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask) | ||
135 | return 0; | ||
136 | #endif | ||
137 | |||
138 | return 1; | 129 | return 1; |
139 | } | 130 | } |
140 | 131 | ||
141 | static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { | 132 | static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { |
142 | [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, | 133 | FRA_GENERIC_POLICY, |
143 | [FRA_PRIORITY] = { .type = NLA_U32 }, | ||
144 | [FRA_SRC] = { .len = sizeof(struct in6_addr) }, | 134 | [FRA_SRC] = { .len = sizeof(struct in6_addr) }, |
145 | [FRA_DST] = { .len = sizeof(struct in6_addr) }, | 135 | [FRA_DST] = { .len = sizeof(struct in6_addr) }, |
146 | [FRA_FWMARK] = { .type = NLA_U32 }, | ||
147 | [FRA_FWMASK] = { .type = NLA_U32 }, | ||
148 | [FRA_TABLE] = { .type = NLA_U32 }, | ||
149 | }; | 136 | }; |
150 | 137 | ||
151 | static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | 138 | static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, |
@@ -155,8 +142,7 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
155 | int err = -EINVAL; | 142 | int err = -EINVAL; |
156 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; | 143 | struct fib6_rule *rule6 = (struct fib6_rule *) rule; |
157 | 144 | ||
158 | if (frh->src_len > 128 || frh->dst_len > 128 || | 145 | if (frh->src_len > 128 || frh->dst_len > 128) |
159 | (frh->tos & ~IPV6_FLOWINFO_MASK)) | ||
160 | goto errout; | 146 | goto errout; |
161 | 147 | ||
162 | if (rule->action == FR_ACT_TO_TBL) { | 148 | if (rule->action == FR_ACT_TO_TBL) { |
@@ -177,23 +163,6 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, | |||
177 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], | 163 | nla_memcpy(&rule6->dst.addr, tb[FRA_DST], |
178 | sizeof(struct in6_addr)); | 164 | sizeof(struct in6_addr)); |
179 | 165 | ||
180 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
181 | if (tb[FRA_FWMARK]) { | ||
182 | rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); | ||
183 | if (rule6->fwmark) { | ||
184 | /* | ||
185 | * if the mark value is non-zero, | ||
186 | * all bits are compared by default | ||
187 | * unless a mask is explicitly specified. | ||
188 | */ | ||
189 | rule6->fwmask = 0xFFFFFFFF; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | if (tb[FRA_FWMASK]) | ||
194 | rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); | ||
195 | #endif | ||
196 | |||
197 | rule6->src.plen = frh->src_len; | 166 | rule6->src.plen = frh->src_len; |
198 | rule6->dst.plen = frh->dst_len; | 167 | rule6->dst.plen = frh->dst_len; |
199 | rule6->tclass = frh->tos; | 168 | rule6->tclass = frh->tos; |
@@ -225,14 +194,6 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, | |||
225 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) | 194 | nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) |
226 | return 0; | 195 | return 0; |
227 | 196 | ||
228 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
229 | if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) | ||
230 | return 0; | ||
231 | |||
232 | if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) | ||
233 | return 0; | ||
234 | #endif | ||
235 | |||
236 | return 1; | 197 | return 1; |
237 | } | 198 | } |
238 | 199 | ||
@@ -254,14 +215,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, | |||
254 | NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), | 215 | NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), |
255 | &rule6->src.addr); | 216 | &rule6->src.addr); |
256 | 217 | ||
257 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | ||
258 | if (rule6->fwmark) | ||
259 | NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); | ||
260 | |||
261 | if (rule6->fwmask || rule6->fwmark) | ||
262 | NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); | ||
263 | #endif | ||
264 | |||
265 | return 0; | 218 | return 0; |
266 | 219 | ||
267 | nla_put_failure: | 220 | nla_put_failure: |
@@ -278,6 +231,12 @@ static u32 fib6_rule_default_pref(void) | |||
278 | return 0x3FFF; | 231 | return 0x3FFF; |
279 | } | 232 | } |
280 | 233 | ||
234 | static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule) | ||
235 | { | ||
236 | return nla_total_size(16) /* dst */ | ||
237 | + nla_total_size(16); /* src */ | ||
238 | } | ||
239 | |||
281 | static struct fib_rules_ops fib6_rules_ops = { | 240 | static struct fib_rules_ops fib6_rules_ops = { |
282 | .family = AF_INET6, | 241 | .family = AF_INET6, |
283 | .rule_size = sizeof(struct fib6_rule), | 242 | .rule_size = sizeof(struct fib6_rule), |
@@ -287,6 +246,7 @@ static struct fib_rules_ops fib6_rules_ops = { | |||
287 | .compare = fib6_rule_compare, | 246 | .compare = fib6_rule_compare, |
288 | .fill = fib6_rule_fill, | 247 | .fill = fib6_rule_fill, |
289 | .default_pref = fib6_rule_default_pref, | 248 | .default_pref = fib6_rule_default_pref, |
249 | .nlmsg_payload = fib6_rule_nlmsg_payload, | ||
290 | .nlgroup = RTNLGRP_IPV6_RULE, | 250 | .nlgroup = RTNLGRP_IPV6_RULE, |
291 | .policy = fib6_rule_policy, | 251 | .policy = fib6_rule_policy, |
292 | .rules_list = &fib6_rules, | 252 | .rules_list = &fib6_rules, |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 4ec876066b3f..3dcc4b7f41b4 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -177,7 +177,8 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type, | |||
177 | */ | 177 | */ |
178 | dst = ip6_route_output(sk, fl); | 178 | dst = ip6_route_output(sk, fl); |
179 | if (dst->error) { | 179 | if (dst->error) { |
180 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 180 | IP6_INC_STATS(ip6_dst_idev(dst), |
181 | IPSTATS_MIB_OUTNOROUTES); | ||
181 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { | 182 | } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) { |
182 | res = 1; | 183 | res = 1; |
183 | } else { | 184 | } else { |
@@ -233,7 +234,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
233 | len, fl->proto, | 234 | len, fl->proto, |
234 | skb->csum); | 235 | skb->csum); |
235 | } else { | 236 | } else { |
236 | u32 tmp_csum = 0; | 237 | __wsum tmp_csum = 0; |
237 | 238 | ||
238 | skb_queue_walk(&sk->sk_write_queue, skb) { | 239 | skb_queue_walk(&sk->sk_write_queue, skb) { |
239 | tmp_csum = csum_add(tmp_csum, skb->csum); | 240 | tmp_csum = csum_add(tmp_csum, skb->csum); |
@@ -241,13 +242,11 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct | |||
241 | 242 | ||
242 | tmp_csum = csum_partial((char *)icmp6h, | 243 | tmp_csum = csum_partial((char *)icmp6h, |
243 | sizeof(struct icmp6hdr), tmp_csum); | 244 | sizeof(struct icmp6hdr), tmp_csum); |
244 | tmp_csum = csum_ipv6_magic(&fl->fl6_src, | 245 | icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, |
245 | &fl->fl6_dst, | 246 | &fl->fl6_dst, |
246 | len, fl->proto, tmp_csum); | 247 | len, fl->proto, |
247 | icmp6h->icmp6_cksum = tmp_csum; | 248 | tmp_csum); |
248 | } | 249 | } |
249 | if (icmp6h->icmp6_cksum == 0) | ||
250 | icmp6h->icmp6_cksum = -1; | ||
251 | ip6_push_pending_frames(sk); | 250 | ip6_push_pending_frames(sk); |
252 | out: | 251 | out: |
253 | return err; | 252 | return err; |
@@ -263,7 +262,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st | |||
263 | { | 262 | { |
264 | struct icmpv6_msg *msg = (struct icmpv6_msg *) from; | 263 | struct icmpv6_msg *msg = (struct icmpv6_msg *) from; |
265 | struct sk_buff *org_skb = msg->skb; | 264 | struct sk_buff *org_skb = msg->skb; |
266 | __u32 csum = 0; | 265 | __wsum csum = 0; |
267 | 266 | ||
268 | csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset, | 267 | csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset, |
269 | to, len, csum); | 268 | to, len, csum); |
@@ -555,7 +554,7 @@ out: | |||
555 | icmpv6_xmit_unlock(); | 554 | icmpv6_xmit_unlock(); |
556 | } | 555 | } |
557 | 556 | ||
558 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) | 557 | static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) |
559 | { | 558 | { |
560 | struct in6_addr *saddr, *daddr; | 559 | struct in6_addr *saddr, *daddr; |
561 | struct inet6_protocol *ipprot; | 560 | struct inet6_protocol *ipprot; |
@@ -637,8 +636,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
637 | break; | 636 | break; |
638 | /* fall through */ | 637 | /* fall through */ |
639 | case CHECKSUM_NONE: | 638 | case CHECKSUM_NONE: |
640 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, | 639 | skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, |
641 | IPPROTO_ICMPV6, 0); | 640 | IPPROTO_ICMPV6, 0)); |
642 | if (__skb_checksum_complete(skb)) { | 641 | if (__skb_checksum_complete(skb)) { |
643 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", | 642 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", |
644 | NIP6(*saddr), NIP6(*daddr)); | 643 | NIP6(*saddr), NIP6(*daddr)); |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 827f41d1478b..c700302ad51a 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -52,20 +52,20 @@ EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); | |||
52 | /* | 52 | /* |
53 | * request_sock (formerly open request) hash tables. | 53 | * request_sock (formerly open request) hash tables. |
54 | */ | 54 | */ |
55 | static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport, | 55 | static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, |
56 | const u32 rnd, const u16 synq_hsize) | 56 | const u32 rnd, const u16 synq_hsize) |
57 | { | 57 | { |
58 | u32 a = raddr->s6_addr32[0]; | 58 | u32 a = (__force u32)raddr->s6_addr32[0]; |
59 | u32 b = raddr->s6_addr32[1]; | 59 | u32 b = (__force u32)raddr->s6_addr32[1]; |
60 | u32 c = raddr->s6_addr32[2]; | 60 | u32 c = (__force u32)raddr->s6_addr32[2]; |
61 | 61 | ||
62 | a += JHASH_GOLDEN_RATIO; | 62 | a += JHASH_GOLDEN_RATIO; |
63 | b += JHASH_GOLDEN_RATIO; | 63 | b += JHASH_GOLDEN_RATIO; |
64 | c += rnd; | 64 | c += rnd; |
65 | __jhash_mix(a, b, c); | 65 | __jhash_mix(a, b, c); |
66 | 66 | ||
67 | a += raddr->s6_addr32[3]; | 67 | a += (__force u32)raddr->s6_addr32[3]; |
68 | b += (u32)rport; | 68 | b += (__force u32)rport; |
69 | __jhash_mix(a, b, c); | 69 | __jhash_mix(a, b, c); |
70 | 70 | ||
71 | return c & (synq_hsize - 1); | 71 | return c & (synq_hsize - 1); |
@@ -73,7 +73,7 @@ static u32 inet6_synq_hash(const struct in6_addr *raddr, const u16 rport, | |||
73 | 73 | ||
74 | struct request_sock *inet6_csk_search_req(const struct sock *sk, | 74 | struct request_sock *inet6_csk_search_req(const struct sock *sk, |
75 | struct request_sock ***prevp, | 75 | struct request_sock ***prevp, |
76 | const __u16 rport, | 76 | const __be16 rport, |
77 | const struct in6_addr *raddr, | 77 | const struct in6_addr *raddr, |
78 | const struct in6_addr *laddr, | 78 | const struct in6_addr *laddr, |
79 | const int iif) | 79 | const int iif) |
@@ -139,9 +139,8 @@ void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr) | |||
139 | 139 | ||
140 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); | 140 | EXPORT_SYMBOL_GPL(inet6_csk_addr2sockaddr); |
141 | 141 | ||
142 | int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) | 142 | int inet6_csk_xmit(struct sk_buff *skb, struct sock *sk, int ipfragok) |
143 | { | 143 | { |
144 | struct sock *sk = skb->sk; | ||
145 | struct inet_sock *inet = inet_sk(sk); | 144 | struct inet_sock *inet = inet_sk(sk); |
146 | struct ipv6_pinfo *np = inet6_sk(sk); | 145 | struct ipv6_pinfo *np = inet6_sk(sk); |
147 | struct flowi fl; | 146 | struct flowi fl; |
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 8accd1fbeeda..b7e5bae0e347 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c | |||
@@ -57,7 +57,7 @@ EXPORT_SYMBOL(__inet6_hash); | |||
57 | */ | 57 | */ |
58 | struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, | 58 | struct sock *__inet6_lookup_established(struct inet_hashinfo *hashinfo, |
59 | const struct in6_addr *saddr, | 59 | const struct in6_addr *saddr, |
60 | const u16 sport, | 60 | const __be16 sport, |
61 | const struct in6_addr *daddr, | 61 | const struct in6_addr *daddr, |
62 | const u16 hnum, | 62 | const u16 hnum, |
63 | const int dif) | 63 | const int dif) |
@@ -146,8 +146,8 @@ struct sock *inet6_lookup_listener(struct inet_hashinfo *hashinfo, | |||
146 | EXPORT_SYMBOL_GPL(inet6_lookup_listener); | 146 | EXPORT_SYMBOL_GPL(inet6_lookup_listener); |
147 | 147 | ||
148 | struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, | 148 | struct sock *inet6_lookup(struct inet_hashinfo *hashinfo, |
149 | const struct in6_addr *saddr, const u16 sport, | 149 | const struct in6_addr *saddr, const __be16 sport, |
150 | const struct in6_addr *daddr, const u16 dport, | 150 | const struct in6_addr *daddr, const __be16 dport, |
151 | const int dif) | 151 | const int dif) |
152 | { | 152 | { |
153 | struct sock *sk; | 153 | struct sock *sk; |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f98ca30d7c1f..bf526115e518 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -139,9 +139,9 @@ static __inline__ u32 fib6_new_sernum(void) | |||
139 | * test bit | 139 | * test bit |
140 | */ | 140 | */ |
141 | 141 | ||
142 | static __inline__ int addr_bit_set(void *token, int fn_bit) | 142 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) |
143 | { | 143 | { |
144 | __u32 *addr = token; | 144 | __be32 *addr = token; |
145 | 145 | ||
146 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; | 146 | return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; |
147 | } | 147 | } |
@@ -434,7 +434,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, | |||
434 | struct fib6_node *pn = NULL; | 434 | struct fib6_node *pn = NULL; |
435 | struct rt6key *key; | 435 | struct rt6key *key; |
436 | int bit; | 436 | int bit; |
437 | int dir = 0; | 437 | __be32 dir = 0; |
438 | __u32 sernum = fib6_new_sernum(); | 438 | __u32 sernum = fib6_new_sernum(); |
439 | 439 | ||
440 | RT6_TRACE("fib6_add_1\n"); | 440 | RT6_TRACE("fib6_add_1\n"); |
@@ -829,7 +829,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | |||
829 | struct lookup_args *args) | 829 | struct lookup_args *args) |
830 | { | 830 | { |
831 | struct fib6_node *fn; | 831 | struct fib6_node *fn; |
832 | int dir; | 832 | __be32 dir; |
833 | 833 | ||
834 | if (unlikely(args->offset == 0)) | 834 | if (unlikely(args->offset == 0)) |
835 | return NULL; | 835 | return NULL; |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 6d4533b58dca..624fae251f4e 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -61,7 +61,7 @@ static DEFINE_RWLOCK(ip6_fl_lock); | |||
61 | static DEFINE_RWLOCK(ip6_sk_fl_lock); | 61 | static DEFINE_RWLOCK(ip6_sk_fl_lock); |
62 | 62 | ||
63 | 63 | ||
64 | static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label) | 64 | static __inline__ struct ip6_flowlabel * __fl_lookup(__be32 label) |
65 | { | 65 | { |
66 | struct ip6_flowlabel *fl; | 66 | struct ip6_flowlabel *fl; |
67 | 67 | ||
@@ -72,7 +72,7 @@ static __inline__ struct ip6_flowlabel * __fl_lookup(u32 label) | |||
72 | return NULL; | 72 | return NULL; |
73 | } | 73 | } |
74 | 74 | ||
75 | static struct ip6_flowlabel * fl_lookup(u32 label) | 75 | static struct ip6_flowlabel * fl_lookup(__be32 label) |
76 | { | 76 | { |
77 | struct ip6_flowlabel *fl; | 77 | struct ip6_flowlabel *fl; |
78 | 78 | ||
@@ -153,7 +153,7 @@ static void ip6_fl_gc(unsigned long dummy) | |||
153 | write_unlock(&ip6_fl_lock); | 153 | write_unlock(&ip6_fl_lock); |
154 | } | 154 | } |
155 | 155 | ||
156 | static int fl_intern(struct ip6_flowlabel *fl, __u32 label) | 156 | static int fl_intern(struct ip6_flowlabel *fl, __be32 label) |
157 | { | 157 | { |
158 | fl->label = label & IPV6_FLOWLABEL_MASK; | 158 | fl->label = label & IPV6_FLOWLABEL_MASK; |
159 | 159 | ||
@@ -182,7 +182,7 @@ static int fl_intern(struct ip6_flowlabel *fl, __u32 label) | |||
182 | 182 | ||
183 | /* Socket flowlabel lists */ | 183 | /* Socket flowlabel lists */ |
184 | 184 | ||
185 | struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, u32 label) | 185 | struct ip6_flowlabel * fl6_sock_lookup(struct sock *sk, __be32 label) |
186 | { | 186 | { |
187 | struct ipv6_fl_socklist *sfl; | 187 | struct ipv6_fl_socklist *sfl; |
188 | struct ipv6_pinfo *np = inet6_sk(sk); | 188 | struct ipv6_pinfo *np = inet6_sk(sk); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 6b8e6d76a58b..ad0b8abcdf4b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -60,14 +60,22 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
60 | { | 60 | { |
61 | struct ipv6hdr *hdr; | 61 | struct ipv6hdr *hdr; |
62 | u32 pkt_len; | 62 | u32 pkt_len; |
63 | struct inet6_dev *idev; | ||
63 | 64 | ||
64 | if (skb->pkt_type == PACKET_OTHERHOST) | 65 | if (skb->pkt_type == PACKET_OTHERHOST) { |
65 | goto drop; | 66 | kfree_skb(skb); |
67 | return 0; | ||
68 | } | ||
69 | |||
70 | rcu_read_lock(); | ||
66 | 71 | ||
67 | IP6_INC_STATS_BH(IPSTATS_MIB_INRECEIVES); | 72 | idev = __in6_dev_get(skb->dev); |
73 | |||
74 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INRECEIVES); | ||
68 | 75 | ||
69 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 76 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
70 | IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); | 77 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); |
78 | rcu_read_unlock(); | ||
71 | goto out; | 79 | goto out; |
72 | } | 80 | } |
73 | 81 | ||
@@ -84,7 +92,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
84 | * arrived via the sending interface (ethX), because of the | 92 | * arrived via the sending interface (ethX), because of the |
85 | * nature of scoping architecture. --yoshfuji | 93 | * nature of scoping architecture. --yoshfuji |
86 | */ | 94 | */ |
87 | IP6CB(skb)->iif = skb->dst ? ((struct rt6_info *)skb->dst)->rt6i_idev->dev->ifindex : dev->ifindex; | 95 | IP6CB(skb)->iif = skb->dst ? ip6_dst_idev(skb->dst)->dev->ifindex : dev->ifindex; |
88 | 96 | ||
89 | if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) | 97 | if (unlikely(!pskb_may_pull(skb, sizeof(*hdr)))) |
90 | goto err; | 98 | goto err; |
@@ -104,7 +112,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
104 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) | 112 | if (pkt_len + sizeof(struct ipv6hdr) > skb->len) |
105 | goto truncated; | 113 | goto truncated; |
106 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { | 114 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) { |
107 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 115 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
108 | goto drop; | 116 | goto drop; |
109 | } | 117 | } |
110 | hdr = skb->nh.ipv6h; | 118 | hdr = skb->nh.ipv6h; |
@@ -112,17 +120,21 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
112 | 120 | ||
113 | if (hdr->nexthdr == NEXTHDR_HOP) { | 121 | if (hdr->nexthdr == NEXTHDR_HOP) { |
114 | if (ipv6_parse_hopopts(&skb) < 0) { | 122 | if (ipv6_parse_hopopts(&skb) < 0) { |
115 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 123 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
124 | rcu_read_unlock(); | ||
116 | return 0; | 125 | return 0; |
117 | } | 126 | } |
118 | } | 127 | } |
119 | 128 | ||
129 | rcu_read_unlock(); | ||
130 | |||
120 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); | 131 | return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish); |
121 | truncated: | 132 | truncated: |
122 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); | 133 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INTRUNCATEDPKTS); |
123 | err: | 134 | err: |
124 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 135 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INHDRERRORS); |
125 | drop: | 136 | drop: |
137 | rcu_read_unlock(); | ||
126 | kfree_skb(skb); | 138 | kfree_skb(skb); |
127 | out: | 139 | out: |
128 | return 0; | 140 | return 0; |
@@ -140,6 +152,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
140 | unsigned int nhoff; | 152 | unsigned int nhoff; |
141 | int nexthdr; | 153 | int nexthdr; |
142 | u8 hash; | 154 | u8 hash; |
155 | struct inet6_dev *idev; | ||
143 | 156 | ||
144 | /* | 157 | /* |
145 | * Parse extension headers | 158 | * Parse extension headers |
@@ -147,6 +160,7 @@ static inline int ip6_input_finish(struct sk_buff *skb) | |||
147 | 160 | ||
148 | rcu_read_lock(); | 161 | rcu_read_lock(); |
149 | resubmit: | 162 | resubmit: |
163 | idev = ip6_dst_idev(skb->dst); | ||
150 | if (!pskb_pull(skb, skb->h.raw - skb->data)) | 164 | if (!pskb_pull(skb, skb->h.raw - skb->data)) |
151 | goto discard; | 165 | goto discard; |
152 | nhoff = IP6CB(skb)->nhoff; | 166 | nhoff = IP6CB(skb)->nhoff; |
@@ -185,24 +199,24 @@ resubmit: | |||
185 | if (ret > 0) | 199 | if (ret > 0) |
186 | goto resubmit; | 200 | goto resubmit; |
187 | else if (ret == 0) | 201 | else if (ret == 0) |
188 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); | 202 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); |
189 | } else { | 203 | } else { |
190 | if (!raw_sk) { | 204 | if (!raw_sk) { |
191 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 205 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
192 | IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); | 206 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); |
193 | icmpv6_send(skb, ICMPV6_PARAMPROB, | 207 | icmpv6_send(skb, ICMPV6_PARAMPROB, |
194 | ICMPV6_UNK_NEXTHDR, nhoff, | 208 | ICMPV6_UNK_NEXTHDR, nhoff, |
195 | skb->dev); | 209 | skb->dev); |
196 | } | 210 | } |
197 | } else | 211 | } else |
198 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); | 212 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); |
199 | kfree_skb(skb); | 213 | kfree_skb(skb); |
200 | } | 214 | } |
201 | rcu_read_unlock(); | 215 | rcu_read_unlock(); |
202 | return 0; | 216 | return 0; |
203 | 217 | ||
204 | discard: | 218 | discard: |
205 | IP6_INC_STATS_BH(IPSTATS_MIB_INDISCARDS); | 219 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDISCARDS); |
206 | rcu_read_unlock(); | 220 | rcu_read_unlock(); |
207 | kfree_skb(skb); | 221 | kfree_skb(skb); |
208 | return 0; | 222 | return 0; |
@@ -219,7 +233,7 @@ int ip6_mc_input(struct sk_buff *skb) | |||
219 | struct ipv6hdr *hdr; | 233 | struct ipv6hdr *hdr; |
220 | int deliver; | 234 | int deliver; |
221 | 235 | ||
222 | IP6_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS); | 236 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INMCASTPKTS); |
223 | 237 | ||
224 | hdr = skb->nh.ipv6h; | 238 | hdr = skb->nh.ipv6h; |
225 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || | 239 | deliver = likely(!(skb->dev->flags & (IFF_PROMISC|IFF_ALLMULTI))) || |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 66716911962e..e05ecbb1412d 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -88,7 +88,7 @@ static inline int ip6_output_finish(struct sk_buff *skb) | |||
88 | } else if (dst->neighbour) | 88 | } else if (dst->neighbour) |
89 | return dst->neighbour->output(skb); | 89 | return dst->neighbour->output(skb); |
90 | 90 | ||
91 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); | 91 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
92 | kfree_skb(skb); | 92 | kfree_skb(skb); |
93 | return -EINVAL; | 93 | return -EINVAL; |
94 | 94 | ||
@@ -118,6 +118,7 @@ static int ip6_output2(struct sk_buff *skb) | |||
118 | 118 | ||
119 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { | 119 | if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr)) { |
120 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; | 120 | struct ipv6_pinfo* np = skb->sk ? inet6_sk(skb->sk) : NULL; |
121 | struct inet6_dev *idev = ip6_dst_idev(skb->dst); | ||
121 | 122 | ||
122 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && | 123 | if (!(dev->flags & IFF_LOOPBACK) && (!np || np->mc_loop) && |
123 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, | 124 | ipv6_chk_mcast_addr(dev, &skb->nh.ipv6h->daddr, |
@@ -133,13 +134,13 @@ static int ip6_output2(struct sk_buff *skb) | |||
133 | ip6_dev_loopback_xmit); | 134 | ip6_dev_loopback_xmit); |
134 | 135 | ||
135 | if (skb->nh.ipv6h->hop_limit == 0) { | 136 | if (skb->nh.ipv6h->hop_limit == 0) { |
136 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 137 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
137 | kfree_skb(skb); | 138 | kfree_skb(skb); |
138 | return 0; | 139 | return 0; |
139 | } | 140 | } |
140 | } | 141 | } |
141 | 142 | ||
142 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 143 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
143 | } | 144 | } |
144 | 145 | ||
145 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); | 146 | return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish); |
@@ -182,12 +183,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
182 | 183 | ||
183 | if (skb_headroom(skb) < head_room) { | 184 | if (skb_headroom(skb) < head_room) { |
184 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); | 185 | struct sk_buff *skb2 = skb_realloc_headroom(skb, head_room); |
185 | kfree_skb(skb); | 186 | if (skb2 == NULL) { |
186 | skb = skb2; | 187 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
187 | if (skb == NULL) { | 188 | IPSTATS_MIB_OUTDISCARDS); |
188 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 189 | kfree_skb(skb); |
189 | return -ENOBUFS; | 190 | return -ENOBUFS; |
190 | } | 191 | } |
192 | kfree_skb(skb); | ||
193 | skb = skb2; | ||
191 | if (sk) | 194 | if (sk) |
192 | skb_set_owner_w(skb, sk); | 195 | skb_set_owner_w(skb, sk); |
193 | } | 196 | } |
@@ -217,7 +220,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
217 | if (tclass < 0) | 220 | if (tclass < 0) |
218 | tclass = 0; | 221 | tclass = 0; |
219 | 222 | ||
220 | *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; | 223 | *(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; |
221 | 224 | ||
222 | hdr->payload_len = htons(seg_len); | 225 | hdr->payload_len = htons(seg_len); |
223 | hdr->nexthdr = proto; | 226 | hdr->nexthdr = proto; |
@@ -230,7 +233,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
230 | 233 | ||
231 | mtu = dst_mtu(dst); | 234 | mtu = dst_mtu(dst); |
232 | if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { | 235 | if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { |
233 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 236 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
237 | IPSTATS_MIB_OUTREQUESTS); | ||
234 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, | 238 | return NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, |
235 | dst_output); | 239 | dst_output); |
236 | } | 240 | } |
@@ -239,7 +243,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
239 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); | 243 | printk(KERN_DEBUG "IPv6: sending pkt_too_big to self\n"); |
240 | skb->dev = dst->dev; | 244 | skb->dev = dst->dev; |
241 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); | 245 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev); |
242 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 246 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
243 | kfree_skb(skb); | 247 | kfree_skb(skb); |
244 | return -EMSGSIZE; | 248 | return -EMSGSIZE; |
245 | } | 249 | } |
@@ -267,7 +271,7 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev, | |||
267 | hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); | 271 | hdr = (struct ipv6hdr *) skb_put(skb, sizeof(struct ipv6hdr)); |
268 | skb->nh.ipv6h = hdr; | 272 | skb->nh.ipv6h = hdr; |
269 | 273 | ||
270 | *(u32*)hdr = htonl(0x60000000); | 274 | *(__be32*)hdr = htonl(0x60000000); |
271 | 275 | ||
272 | hdr->payload_len = htons(len); | 276 | hdr->payload_len = htons(len); |
273 | hdr->nexthdr = proto; | 277 | hdr->nexthdr = proto; |
@@ -373,7 +377,7 @@ int ip6_forward(struct sk_buff *skb) | |||
373 | goto error; | 377 | goto error; |
374 | 378 | ||
375 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { | 379 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_FWD, skb)) { |
376 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 380 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
377 | goto drop; | 381 | goto drop; |
378 | } | 382 | } |
379 | 383 | ||
@@ -406,7 +410,7 @@ int ip6_forward(struct sk_buff *skb) | |||
406 | skb->dev = dst->dev; | 410 | skb->dev = dst->dev; |
407 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, | 411 | icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, |
408 | 0, skb->dev); | 412 | 0, skb->dev); |
409 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 413 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
410 | 414 | ||
411 | kfree_skb(skb); | 415 | kfree_skb(skb); |
412 | return -ETIMEDOUT; | 416 | return -ETIMEDOUT; |
@@ -419,13 +423,13 @@ int ip6_forward(struct sk_buff *skb) | |||
419 | if (proxied > 0) | 423 | if (proxied > 0) |
420 | return ip6_input(skb); | 424 | return ip6_input(skb); |
421 | else if (proxied < 0) { | 425 | else if (proxied < 0) { |
422 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 426 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
423 | goto drop; | 427 | goto drop; |
424 | } | 428 | } |
425 | } | 429 | } |
426 | 430 | ||
427 | if (!xfrm6_route_forward(skb)) { | 431 | if (!xfrm6_route_forward(skb)) { |
428 | IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); | 432 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_INDISCARDS); |
429 | goto drop; | 433 | goto drop; |
430 | } | 434 | } |
431 | dst = skb->dst; | 435 | dst = skb->dst; |
@@ -464,14 +468,14 @@ int ip6_forward(struct sk_buff *skb) | |||
464 | /* Again, force OUTPUT device used as source address */ | 468 | /* Again, force OUTPUT device used as source address */ |
465 | skb->dev = dst->dev; | 469 | skb->dev = dst->dev; |
466 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); | 470 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst_mtu(dst), skb->dev); |
467 | IP6_INC_STATS_BH(IPSTATS_MIB_INTOOBIGERRORS); | 471 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INTOOBIGERRORS); |
468 | IP6_INC_STATS_BH(IPSTATS_MIB_FRAGFAILS); | 472 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_FRAGFAILS); |
469 | kfree_skb(skb); | 473 | kfree_skb(skb); |
470 | return -EMSGSIZE; | 474 | return -EMSGSIZE; |
471 | } | 475 | } |
472 | 476 | ||
473 | if (skb_cow(skb, dst->dev->hard_header_len)) { | 477 | if (skb_cow(skb, dst->dev->hard_header_len)) { |
474 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 478 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTDISCARDS); |
475 | goto drop; | 479 | goto drop; |
476 | } | 480 | } |
477 | 481 | ||
@@ -481,11 +485,11 @@ int ip6_forward(struct sk_buff *skb) | |||
481 | 485 | ||
482 | hdr->hop_limit--; | 486 | hdr->hop_limit--; |
483 | 487 | ||
484 | IP6_INC_STATS_BH(IPSTATS_MIB_OUTFORWDATAGRAMS); | 488 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_OUTFORWDATAGRAMS); |
485 | return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); | 489 | return NF_HOOK(PF_INET6,NF_IP6_FORWARD, skb, skb->dev, dst->dev, ip6_forward_finish); |
486 | 490 | ||
487 | error: | 491 | error: |
488 | IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); | 492 | IP6_INC_STATS_BH(ip6_dst_idev(dst), IPSTATS_MIB_INADDRERRORS); |
489 | drop: | 493 | drop: |
490 | kfree_skb(skb); | 494 | kfree_skb(skb); |
491 | return -EINVAL; | 495 | return -EINVAL; |
@@ -499,12 +503,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) | |||
499 | dst_release(to->dst); | 503 | dst_release(to->dst); |
500 | to->dst = dst_clone(from->dst); | 504 | to->dst = dst_clone(from->dst); |
501 | to->dev = from->dev; | 505 | to->dev = from->dev; |
506 | to->mark = from->mark; | ||
502 | 507 | ||
503 | #ifdef CONFIG_NET_SCHED | 508 | #ifdef CONFIG_NET_SCHED |
504 | to->tc_index = from->tc_index; | 509 | to->tc_index = from->tc_index; |
505 | #endif | 510 | #endif |
506 | #ifdef CONFIG_NETFILTER | 511 | #ifdef CONFIG_NETFILTER |
507 | to->nfmark = from->nfmark; | ||
508 | /* Connection association is same as pre-frag packet */ | 512 | /* Connection association is same as pre-frag packet */ |
509 | nf_conntrack_put(to->nfct); | 513 | nf_conntrack_put(to->nfct); |
510 | to->nfct = from->nfct; | 514 | to->nfct = from->nfct; |
@@ -571,7 +575,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
571 | struct ipv6hdr *tmp_hdr; | 575 | struct ipv6hdr *tmp_hdr; |
572 | struct frag_hdr *fh; | 576 | struct frag_hdr *fh; |
573 | unsigned int mtu, hlen, left, len; | 577 | unsigned int mtu, hlen, left, len; |
574 | u32 frag_id = 0; | 578 | __be32 frag_id = 0; |
575 | int ptr, offset = 0, err=0; | 579 | int ptr, offset = 0, err=0; |
576 | u8 *prevhdr, nexthdr = 0; | 580 | u8 *prevhdr, nexthdr = 0; |
577 | 581 | ||
@@ -620,14 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
620 | skb_shinfo(skb)->frag_list = NULL; | 624 | skb_shinfo(skb)->frag_list = NULL; |
621 | /* BUILD HEADER */ | 625 | /* BUILD HEADER */ |
622 | 626 | ||
623 | tmp_hdr = kmalloc(hlen, GFP_ATOMIC); | 627 | tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); |
624 | if (!tmp_hdr) { | 628 | if (!tmp_hdr) { |
625 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 629 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); |
626 | return -ENOMEM; | 630 | return -ENOMEM; |
627 | } | 631 | } |
628 | 632 | ||
629 | *prevhdr = NEXTHDR_FRAGMENT; | 633 | *prevhdr = NEXTHDR_FRAGMENT; |
630 | memcpy(tmp_hdr, skb->nh.raw, hlen); | ||
631 | __skb_pull(skb, hlen); | 634 | __skb_pull(skb, hlen); |
632 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); | 635 | fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); |
633 | skb->nh.raw = __skb_push(skb, hlen); | 636 | skb->nh.raw = __skb_push(skb, hlen); |
@@ -643,7 +646,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
643 | skb->data_len = first_len - skb_headlen(skb); | 646 | skb->data_len = first_len - skb_headlen(skb); |
644 | skb->len = first_len; | 647 | skb->len = first_len; |
645 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); | 648 | skb->nh.ipv6h->payload_len = htons(first_len - sizeof(struct ipv6hdr)); |
646 | 649 | ||
650 | dst_hold(&rt->u.dst); | ||
647 | 651 | ||
648 | for (;;) { | 652 | for (;;) { |
649 | /* Prepare header of the next frame, | 653 | /* Prepare header of the next frame, |
@@ -667,7 +671,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
667 | 671 | ||
668 | err = output(skb); | 672 | err = output(skb); |
669 | if(!err) | 673 | if(!err) |
670 | IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); | 674 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGCREATES); |
671 | 675 | ||
672 | if (err || !frag) | 676 | if (err || !frag) |
673 | break; | 677 | break; |
@@ -680,7 +684,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
680 | kfree(tmp_hdr); | 684 | kfree(tmp_hdr); |
681 | 685 | ||
682 | if (err == 0) { | 686 | if (err == 0) { |
683 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); | 687 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGOKS); |
688 | dst_release(&rt->u.dst); | ||
684 | return 0; | 689 | return 0; |
685 | } | 690 | } |
686 | 691 | ||
@@ -690,7 +695,8 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
690 | frag = skb; | 695 | frag = skb; |
691 | } | 696 | } |
692 | 697 | ||
693 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 698 | IP6_INC_STATS(ip6_dst_idev(&rt->u.dst), IPSTATS_MIB_FRAGFAILS); |
699 | dst_release(&rt->u.dst); | ||
694 | return err; | 700 | return err; |
695 | } | 701 | } |
696 | 702 | ||
@@ -723,7 +729,8 @@ slow_path: | |||
723 | 729 | ||
724 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { | 730 | if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { |
725 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); | 731 | NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); |
726 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | 732 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
733 | IPSTATS_MIB_FRAGFAILS); | ||
727 | err = -ENOMEM; | 734 | err = -ENOMEM; |
728 | goto fail; | 735 | goto fail; |
729 | } | 736 | } |
@@ -784,15 +791,17 @@ slow_path: | |||
784 | if (err) | 791 | if (err) |
785 | goto fail; | 792 | goto fail; |
786 | 793 | ||
787 | IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); | 794 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGCREATES); |
788 | } | 795 | } |
796 | IP6_INC_STATS(ip6_dst_idev(skb->dst), | ||
797 | IPSTATS_MIB_FRAGOKS); | ||
789 | kfree_skb(skb); | 798 | kfree_skb(skb); |
790 | IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); | ||
791 | return err; | 799 | return err; |
792 | 800 | ||
793 | fail: | 801 | fail: |
802 | IP6_INC_STATS(ip6_dst_idev(skb->dst), | ||
803 | IPSTATS_MIB_FRAGFAILS); | ||
794 | kfree_skb(skb); | 804 | kfree_skb(skb); |
795 | IP6_INC_STATS(IPSTATS_MIB_FRAGFAILS); | ||
796 | return err; | 805 | return err; |
797 | } | 806 | } |
798 | 807 | ||
@@ -1265,7 +1274,7 @@ alloc_new_skb: | |||
1265 | return 0; | 1274 | return 0; |
1266 | error: | 1275 | error: |
1267 | inet->cork.length -= length; | 1276 | inet->cork.length -= length; |
1268 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1277 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); |
1269 | return err; | 1278 | return err; |
1270 | } | 1279 | } |
1271 | 1280 | ||
@@ -1311,7 +1320,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1311 | 1320 | ||
1312 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); | 1321 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); |
1313 | 1322 | ||
1314 | *(u32*)hdr = fl->fl6_flowlabel | | 1323 | *(__be32*)hdr = fl->fl6_flowlabel | |
1315 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | 1324 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); |
1316 | 1325 | ||
1317 | if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) | 1326 | if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) |
@@ -1326,7 +1335,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1326 | skb->priority = sk->sk_priority; | 1335 | skb->priority = sk->sk_priority; |
1327 | 1336 | ||
1328 | skb->dst = dst_clone(&rt->u.dst); | 1337 | skb->dst = dst_clone(&rt->u.dst); |
1329 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1338 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); |
1330 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); | 1339 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); |
1331 | if (err) { | 1340 | if (err) { |
1332 | if (err > 0) | 1341 | if (err > 0) |
@@ -1357,7 +1366,8 @@ void ip6_flush_pending_frames(struct sock *sk) | |||
1357 | struct sk_buff *skb; | 1366 | struct sk_buff *skb; |
1358 | 1367 | ||
1359 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { | 1368 | while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) { |
1360 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1369 | IP6_INC_STATS(ip6_dst_idev(skb->dst), |
1370 | IPSTATS_MIB_OUTDISCARDS); | ||
1361 | kfree_skb(skb); | 1371 | kfree_skb(skb); |
1362 | } | 1372 | } |
1363 | 1373 | ||
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index b9f40290d12a..8d918348f5bb 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); | |||
66 | 66 | ||
67 | #define HASH_SIZE 32 | 67 | #define HASH_SIZE 32 |
68 | 68 | ||
69 | #define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ | 69 | #define HASH(addr) ((__force u32)((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ |
70 | (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ | 70 | (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ |
71 | (HASH_SIZE - 1)) | 71 | (HASH_SIZE - 1)) |
72 | 72 | ||
@@ -215,11 +215,10 @@ ip6ip6_tnl_unlink(struct ip6_tnl *t) | |||
215 | * Create tunnel matching given parameters. | 215 | * Create tunnel matching given parameters. |
216 | * | 216 | * |
217 | * Return: | 217 | * Return: |
218 | * 0 on success | 218 | * created tunnel or NULL |
219 | **/ | 219 | **/ |
220 | 220 | ||
221 | static int | 221 | static struct ip6_tnl *ip6_tnl_create(struct ip6_tnl_parm *p) |
222 | ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) | ||
223 | { | 222 | { |
224 | struct net_device *dev; | 223 | struct net_device *dev; |
225 | struct ip6_tnl *t; | 224 | struct ip6_tnl *t; |
@@ -236,11 +235,11 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) | |||
236 | break; | 235 | break; |
237 | } | 236 | } |
238 | if (i == IP6_TNL_MAX) | 237 | if (i == IP6_TNL_MAX) |
239 | return -ENOBUFS; | 238 | goto failed; |
240 | } | 239 | } |
241 | dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup); | 240 | dev = alloc_netdev(sizeof (*t), name, ip6ip6_tnl_dev_setup); |
242 | if (dev == NULL) | 241 | if (dev == NULL) |
243 | return -ENOMEM; | 242 | goto failed; |
244 | 243 | ||
245 | t = netdev_priv(dev); | 244 | t = netdev_priv(dev); |
246 | dev->init = ip6ip6_tnl_dev_init; | 245 | dev->init = ip6ip6_tnl_dev_init; |
@@ -248,13 +247,13 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) | |||
248 | 247 | ||
249 | if ((err = register_netdevice(dev)) < 0) { | 248 | if ((err = register_netdevice(dev)) < 0) { |
250 | free_netdev(dev); | 249 | free_netdev(dev); |
251 | return err; | 250 | goto failed; |
252 | } | 251 | } |
253 | dev_hold(dev); | 252 | dev_hold(dev); |
254 | |||
255 | ip6ip6_tnl_link(t); | 253 | ip6ip6_tnl_link(t); |
256 | *pt = t; | 254 | return t; |
257 | return 0; | 255 | failed: |
256 | return NULL; | ||
258 | } | 257 | } |
259 | 258 | ||
260 | /** | 259 | /** |
@@ -268,32 +267,23 @@ ip6_tnl_create(struct ip6_tnl_parm *p, struct ip6_tnl **pt) | |||
268 | * tunnel device is created and registered for use. | 267 | * tunnel device is created and registered for use. |
269 | * | 268 | * |
270 | * Return: | 269 | * Return: |
271 | * 0 if tunnel located or created, | 270 | * matching tunnel or NULL |
272 | * -EINVAL if parameters incorrect, | ||
273 | * -ENODEV if no matching tunnel available | ||
274 | **/ | 271 | **/ |
275 | 272 | ||
276 | static int | 273 | static struct ip6_tnl *ip6ip6_tnl_locate(struct ip6_tnl_parm *p, int create) |
277 | ip6ip6_tnl_locate(struct ip6_tnl_parm *p, struct ip6_tnl **pt, int create) | ||
278 | { | 274 | { |
279 | struct in6_addr *remote = &p->raddr; | 275 | struct in6_addr *remote = &p->raddr; |
280 | struct in6_addr *local = &p->laddr; | 276 | struct in6_addr *local = &p->laddr; |
281 | struct ip6_tnl *t; | 277 | struct ip6_tnl *t; |
282 | 278 | ||
283 | if (p->proto != IPPROTO_IPV6) | ||
284 | return -EINVAL; | ||
285 | |||
286 | for (t = *ip6ip6_bucket(p); t; t = t->next) { | 279 | for (t = *ip6ip6_bucket(p); t; t = t->next) { |
287 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 280 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
288 | ipv6_addr_equal(remote, &t->parms.raddr)) { | 281 | ipv6_addr_equal(remote, &t->parms.raddr)) |
289 | *pt = t; | 282 | return t; |
290 | return (create ? -EEXIST : 0); | ||
291 | } | ||
292 | } | 283 | } |
293 | if (!create) | 284 | if (!create) |
294 | return -ENODEV; | 285 | return NULL; |
295 | 286 | return ip6_tnl_create(p); | |
296 | return ip6_tnl_create(p, pt); | ||
297 | } | 287 | } |
298 | 288 | ||
299 | /** | 289 | /** |
@@ -391,7 +381,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
391 | 381 | ||
392 | static int | 382 | static int |
393 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 383 | ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
394 | int type, int code, int offset, __u32 info) | 384 | int type, int code, int offset, __be32 info) |
395 | { | 385 | { |
396 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 386 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; |
397 | struct ip6_tnl *t; | 387 | struct ip6_tnl *t; |
@@ -434,12 +424,9 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
434 | } | 424 | } |
435 | break; | 425 | break; |
436 | case ICMPV6_PARAMPROB: | 426 | case ICMPV6_PARAMPROB: |
437 | /* ignore if parameter problem not caused by a tunnel | 427 | teli = 0; |
438 | encapsulation limit sub-option */ | 428 | if (code == ICMPV6_HDR_FIELD) |
439 | if (code != ICMPV6_HDR_FIELD) { | 429 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); |
440 | break; | ||
441 | } | ||
442 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); | ||
443 | 430 | ||
444 | if (teli && teli == ntohl(info) - 2) { | 431 | if (teli && teli == ntohl(info) - 2) { |
445 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 432 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
@@ -451,6 +438,10 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
451 | "tunnel!\n", t->parms.name); | 438 | "tunnel!\n", t->parms.name); |
452 | rel_msg = 1; | 439 | rel_msg = 1; |
453 | } | 440 | } |
441 | } else if (net_ratelimit()) { | ||
442 | printk(KERN_WARNING | ||
443 | "%s: Recipient unable to parse tunneled " | ||
444 | "packet!\n ", t->parms.name); | ||
454 | } | 445 | } |
455 | break; | 446 | break; |
456 | case ICMPV6_PKT_TOOBIG: | 447 | case ICMPV6_PKT_TOOBIG: |
@@ -470,6 +461,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
470 | if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) { | 461 | if (rel_msg && pskb_may_pull(skb, offset + sizeof (*ipv6h))) { |
471 | struct rt6_info *rt; | 462 | struct rt6_info *rt; |
472 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | 463 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); |
464 | |||
473 | if (!skb2) | 465 | if (!skb2) |
474 | goto out; | 466 | goto out; |
475 | 467 | ||
@@ -504,6 +496,27 @@ static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, | |||
504 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | 496 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) |
505 | IP6_ECN_set_ce(inner_iph); | 497 | IP6_ECN_set_ce(inner_iph); |
506 | } | 498 | } |
499 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | ||
500 | { | ||
501 | struct ip6_tnl_parm *p = &t->parms; | ||
502 | int ret = 0; | ||
503 | |||
504 | if (p->flags & IP6_TNL_F_CAP_RCV) { | ||
505 | struct net_device *ldev = NULL; | ||
506 | |||
507 | if (p->link) | ||
508 | ldev = dev_get_by_index(p->link); | ||
509 | |||
510 | if ((ipv6_addr_is_multicast(&p->laddr) || | ||
511 | likely(ipv6_chk_addr(&p->laddr, ldev, 0))) && | ||
512 | likely(!ipv6_chk_addr(&p->raddr, NULL, 0))) | ||
513 | ret = 1; | ||
514 | |||
515 | if (ldev) | ||
516 | dev_put(ldev); | ||
517 | } | ||
518 | return ret; | ||
519 | } | ||
507 | 520 | ||
508 | /** | 521 | /** |
509 | * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally | 522 | * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally |
@@ -528,7 +541,7 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
528 | goto discard; | 541 | goto discard; |
529 | } | 542 | } |
530 | 543 | ||
531 | if (!(t->parms.flags & IP6_TNL_F_CAP_RCV)) { | 544 | if (!ip6_tnl_rcv_ctl(t)) { |
532 | t->stat.rx_dropped++; | 545 | t->stat.rx_dropped++; |
533 | read_unlock(&ip6ip6_lock); | 546 | read_unlock(&ip6ip6_lock); |
534 | goto discard; | 547 | goto discard; |
@@ -560,31 +573,23 @@ discard: | |||
560 | return 0; | 573 | return 0; |
561 | } | 574 | } |
562 | 575 | ||
563 | static inline struct ipv6_txoptions *create_tel(__u8 encap_limit) | 576 | struct ipv6_tel_txoption { |
564 | { | 577 | struct ipv6_txoptions ops; |
565 | struct ipv6_tlv_tnl_enc_lim *tel; | 578 | __u8 dst_opt[8]; |
566 | struct ipv6_txoptions *opt; | 579 | }; |
567 | __u8 *raw; | ||
568 | |||
569 | int opt_len = sizeof(*opt) + 8; | ||
570 | |||
571 | if (!(opt = kzalloc(opt_len, GFP_ATOMIC))) { | ||
572 | return NULL; | ||
573 | } | ||
574 | opt->tot_len = opt_len; | ||
575 | opt->dst0opt = (struct ipv6_opt_hdr *) (opt + 1); | ||
576 | opt->opt_nflen = 8; | ||
577 | 580 | ||
578 | tel = (struct ipv6_tlv_tnl_enc_lim *) (opt->dst0opt + 1); | 581 | static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) |
579 | tel->type = IPV6_TLV_TNL_ENCAP_LIMIT; | 582 | { |
580 | tel->length = 1; | 583 | memset(opt, 0, sizeof(struct ipv6_tel_txoption)); |
581 | tel->encap_limit = encap_limit; | ||
582 | 584 | ||
583 | raw = (__u8 *) opt->dst0opt; | 585 | opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT; |
584 | raw[5] = IPV6_TLV_PADN; | 586 | opt->dst_opt[3] = 1; |
585 | raw[6] = 1; | 587 | opt->dst_opt[4] = encap_limit; |
588 | opt->dst_opt[5] = IPV6_TLV_PADN; | ||
589 | opt->dst_opt[6] = 1; | ||
586 | 590 | ||
587 | return opt; | 591 | opt->ops.dst0opt = (struct ipv6_opt_hdr *) opt->dst_opt; |
592 | opt->ops.opt_nflen = 8; | ||
588 | } | 593 | } |
589 | 594 | ||
590 | /** | 595 | /** |
@@ -607,6 +612,34 @@ ip6ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) | |||
607 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | 612 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); |
608 | } | 613 | } |
609 | 614 | ||
615 | static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | ||
616 | { | ||
617 | struct ip6_tnl_parm *p = &t->parms; | ||
618 | int ret = 0; | ||
619 | |||
620 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | ||
621 | struct net_device *ldev = NULL; | ||
622 | |||
623 | if (p->link) | ||
624 | ldev = dev_get_by_index(p->link); | ||
625 | |||
626 | if (unlikely(!ipv6_chk_addr(&p->laddr, ldev, 0))) | ||
627 | printk(KERN_WARNING | ||
628 | "%s xmit: Local address not yet configured!\n", | ||
629 | p->name); | ||
630 | else if (!ipv6_addr_is_multicast(&p->raddr) && | ||
631 | unlikely(ipv6_chk_addr(&p->raddr, NULL, 0))) | ||
632 | printk(KERN_WARNING | ||
633 | "%s xmit: Routing loop! " | ||
634 | "Remote address found on this node!\n", | ||
635 | p->name); | ||
636 | else | ||
637 | ret = 1; | ||
638 | if (ldev) | ||
639 | dev_put(ldev); | ||
640 | } | ||
641 | return ret; | ||
642 | } | ||
610 | /** | 643 | /** |
611 | * ip6ip6_tnl_xmit - encapsulate packet and send | 644 | * ip6ip6_tnl_xmit - encapsulate packet and send |
612 | * @skb: the outgoing socket buffer | 645 | * @skb: the outgoing socket buffer |
@@ -626,8 +659,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
626 | struct ip6_tnl *t = netdev_priv(dev); | 659 | struct ip6_tnl *t = netdev_priv(dev); |
627 | struct net_device_stats *stats = &t->stat; | 660 | struct net_device_stats *stats = &t->stat; |
628 | struct ipv6hdr *ipv6h = skb->nh.ipv6h; | 661 | struct ipv6hdr *ipv6h = skb->nh.ipv6h; |
629 | struct ipv6_txoptions *opt = NULL; | ||
630 | int encap_limit = -1; | 662 | int encap_limit = -1; |
663 | struct ipv6_tel_txoption opt; | ||
631 | __u16 offset; | 664 | __u16 offset; |
632 | struct flowi fl; | 665 | struct flowi fl; |
633 | struct dst_entry *dst; | 666 | struct dst_entry *dst; |
@@ -644,10 +677,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
644 | goto tx_err; | 677 | goto tx_err; |
645 | } | 678 | } |
646 | if (skb->protocol != htons(ETH_P_IPV6) || | 679 | if (skb->protocol != htons(ETH_P_IPV6) || |
647 | !(t->parms.flags & IP6_TNL_F_CAP_XMIT) || | 680 | !ip6_tnl_xmit_ctl(t) || ip6ip6_tnl_addr_conflict(t, ipv6h)) |
648 | ip6ip6_tnl_addr_conflict(t, ipv6h)) { | ||
649 | goto tx_err; | 681 | goto tx_err; |
650 | } | 682 | |
651 | if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { | 683 | if ((offset = parse_tlv_tnl_enc_lim(skb, skb->nh.raw)) > 0) { |
652 | struct ipv6_tlv_tnl_enc_lim *tel; | 684 | struct ipv6_tlv_tnl_enc_lim *tel; |
653 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; | 685 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->nh.raw[offset]; |
@@ -657,20 +689,17 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
657 | goto tx_err; | 689 | goto tx_err; |
658 | } | 690 | } |
659 | encap_limit = tel->encap_limit - 1; | 691 | encap_limit = tel->encap_limit - 1; |
660 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) { | 692 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) |
661 | encap_limit = t->parms.encap_limit; | 693 | encap_limit = t->parms.encap_limit; |
662 | } | 694 | |
663 | memcpy(&fl, &t->fl, sizeof (fl)); | 695 | memcpy(&fl, &t->fl, sizeof (fl)); |
664 | proto = fl.proto; | 696 | proto = fl.proto; |
665 | 697 | ||
666 | dsfield = ipv6_get_dsfield(ipv6h); | 698 | dsfield = ipv6_get_dsfield(ipv6h); |
667 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 699 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) |
668 | fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_TCLASS_MASK); | 700 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); |
669 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | 701 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) |
670 | fl.fl6_flowlabel |= (*(__u32 *) ipv6h & IPV6_FLOWLABEL_MASK); | 702 | fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); |
671 | |||
672 | if (encap_limit >= 0 && (opt = create_tel(encap_limit)) == NULL) | ||
673 | goto tx_err; | ||
674 | 703 | ||
675 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 704 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
676 | dst_hold(dst); | 705 | dst_hold(dst); |
@@ -692,7 +721,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
692 | goto tx_err_dst_release; | 721 | goto tx_err_dst_release; |
693 | } | 722 | } |
694 | mtu = dst_mtu(dst) - sizeof (*ipv6h); | 723 | mtu = dst_mtu(dst) - sizeof (*ipv6h); |
695 | if (opt) { | 724 | if (encap_limit >= 0) { |
696 | max_headroom += 8; | 725 | max_headroom += 8; |
697 | mtu -= 8; | 726 | mtu -= 8; |
698 | } | 727 | } |
@@ -730,12 +759,13 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
730 | 759 | ||
731 | skb->h.raw = skb->nh.raw; | 760 | skb->h.raw = skb->nh.raw; |
732 | 761 | ||
733 | if (opt) | 762 | if (encap_limit >= 0) { |
734 | ipv6_push_nfrag_opts(skb, opt, &proto, NULL); | 763 | init_tel_txopt(&opt, encap_limit); |
735 | 764 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); | |
765 | } | ||
736 | skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr)); | 766 | skb->nh.raw = skb_push(skb, sizeof(struct ipv6hdr)); |
737 | ipv6h = skb->nh.ipv6h; | 767 | ipv6h = skb->nh.ipv6h; |
738 | *(u32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); | 768 | *(__be32*)ipv6h = fl.fl6_flowlabel | htonl(0x60000000); |
739 | dsfield = INET_ECN_encapsulate(0, dsfield); | 769 | dsfield = INET_ECN_encapsulate(0, dsfield); |
740 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); | 770 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); |
741 | ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | 771 | ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); |
@@ -748,7 +778,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
748 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, | 778 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, |
749 | skb->dst->dev, dst_output); | 779 | skb->dst->dev, dst_output); |
750 | 780 | ||
751 | if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { | 781 | if (net_xmit_eval(err) == 0) { |
752 | stats->tx_bytes += pkt_len; | 782 | stats->tx_bytes += pkt_len; |
753 | stats->tx_packets++; | 783 | stats->tx_packets++; |
754 | } else { | 784 | } else { |
@@ -756,9 +786,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
756 | stats->tx_aborted_errors++; | 786 | stats->tx_aborted_errors++; |
757 | } | 787 | } |
758 | ip6_tnl_dst_store(t, dst); | 788 | ip6_tnl_dst_store(t, dst); |
759 | |||
760 | kfree(opt); | ||
761 | |||
762 | t->recursion--; | 789 | t->recursion--; |
763 | return 0; | 790 | return 0; |
764 | tx_err_link_failure: | 791 | tx_err_link_failure: |
@@ -766,7 +793,6 @@ tx_err_link_failure: | |||
766 | dst_link_failure(skb); | 793 | dst_link_failure(skb); |
767 | tx_err_dst_release: | 794 | tx_err_dst_release: |
768 | dst_release(dst); | 795 | dst_release(dst); |
769 | kfree(opt); | ||
770 | tx_err: | 796 | tx_err: |
771 | stats->tx_errors++; | 797 | stats->tx_errors++; |
772 | stats->tx_dropped++; | 798 | stats->tx_dropped++; |
@@ -778,39 +804,19 @@ tx_err: | |||
778 | static void ip6_tnl_set_cap(struct ip6_tnl *t) | 804 | static void ip6_tnl_set_cap(struct ip6_tnl *t) |
779 | { | 805 | { |
780 | struct ip6_tnl_parm *p = &t->parms; | 806 | struct ip6_tnl_parm *p = &t->parms; |
781 | struct in6_addr *laddr = &p->laddr; | 807 | int ltype = ipv6_addr_type(&p->laddr); |
782 | struct in6_addr *raddr = &p->raddr; | 808 | int rtype = ipv6_addr_type(&p->raddr); |
783 | int ltype = ipv6_addr_type(laddr); | ||
784 | int rtype = ipv6_addr_type(raddr); | ||
785 | 809 | ||
786 | p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV); | 810 | p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV); |
787 | 811 | ||
788 | if (ltype != IPV6_ADDR_ANY && rtype != IPV6_ADDR_ANY && | 812 | if (ltype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && |
789 | ((ltype|rtype) & | 813 | rtype & (IPV6_ADDR_UNICAST|IPV6_ADDR_MULTICAST) && |
790 | (IPV6_ADDR_UNICAST| | 814 | !((ltype|rtype) & IPV6_ADDR_LOOPBACK) && |
791 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL| | 815 | (!((ltype|rtype) & IPV6_ADDR_LINKLOCAL) || p->link)) { |
792 | IPV6_ADDR_MAPPED|IPV6_ADDR_RESERVED)) == IPV6_ADDR_UNICAST) { | 816 | if (ltype&IPV6_ADDR_UNICAST) |
793 | struct net_device *ldev = NULL; | 817 | p->flags |= IP6_TNL_F_CAP_XMIT; |
794 | int l_ok = 1; | 818 | if (rtype&IPV6_ADDR_UNICAST) |
795 | int r_ok = 1; | 819 | p->flags |= IP6_TNL_F_CAP_RCV; |
796 | |||
797 | if (p->link) | ||
798 | ldev = dev_get_by_index(p->link); | ||
799 | |||
800 | if (ltype&IPV6_ADDR_UNICAST && !ipv6_chk_addr(laddr, ldev, 0)) | ||
801 | l_ok = 0; | ||
802 | |||
803 | if (rtype&IPV6_ADDR_UNICAST && ipv6_chk_addr(raddr, NULL, 0)) | ||
804 | r_ok = 0; | ||
805 | |||
806 | if (l_ok && r_ok) { | ||
807 | if (ltype&IPV6_ADDR_UNICAST) | ||
808 | p->flags |= IP6_TNL_F_CAP_XMIT; | ||
809 | if (rtype&IPV6_ADDR_UNICAST) | ||
810 | p->flags |= IP6_TNL_F_CAP_RCV; | ||
811 | } | ||
812 | if (ldev) | ||
813 | dev_put(ldev); | ||
814 | } | 820 | } |
815 | } | 821 | } |
816 | 822 | ||
@@ -844,8 +850,11 @@ static void ip6ip6_tnl_link_config(struct ip6_tnl *t) | |||
844 | dev->iflink = p->link; | 850 | dev->iflink = p->link; |
845 | 851 | ||
846 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | 852 | if (p->flags & IP6_TNL_F_CAP_XMIT) { |
853 | int strict = (ipv6_addr_type(&p->raddr) & | ||
854 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); | ||
855 | |||
847 | struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, | 856 | struct rt6_info *rt = rt6_lookup(&p->raddr, &p->laddr, |
848 | p->link, 0); | 857 | p->link, strict); |
849 | 858 | ||
850 | if (rt == NULL) | 859 | if (rt == NULL) |
851 | return; | 860 | return; |
@@ -920,26 +929,20 @@ static int | |||
920 | ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 929 | ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
921 | { | 930 | { |
922 | int err = 0; | 931 | int err = 0; |
923 | int create; | ||
924 | struct ip6_tnl_parm p; | 932 | struct ip6_tnl_parm p; |
925 | struct ip6_tnl *t = NULL; | 933 | struct ip6_tnl *t = NULL; |
926 | 934 | ||
927 | switch (cmd) { | 935 | switch (cmd) { |
928 | case SIOCGETTUNNEL: | 936 | case SIOCGETTUNNEL: |
929 | if (dev == ip6ip6_fb_tnl_dev) { | 937 | if (dev == ip6ip6_fb_tnl_dev) { |
930 | if (copy_from_user(&p, | 938 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { |
931 | ifr->ifr_ifru.ifru_data, | ||
932 | sizeof (p))) { | ||
933 | err = -EFAULT; | 939 | err = -EFAULT; |
934 | break; | 940 | break; |
935 | } | 941 | } |
936 | if ((err = ip6ip6_tnl_locate(&p, &t, 0)) == -ENODEV) | 942 | t = ip6ip6_tnl_locate(&p, 0); |
937 | t = netdev_priv(dev); | 943 | } |
938 | else if (err) | 944 | if (t == NULL) |
939 | break; | ||
940 | } else | ||
941 | t = netdev_priv(dev); | 945 | t = netdev_priv(dev); |
942 | |||
943 | memcpy(&p, &t->parms, sizeof (p)); | 946 | memcpy(&p, &t->parms, sizeof (p)); |
944 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { | 947 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { |
945 | err = -EFAULT; | 948 | err = -EFAULT; |
@@ -948,35 +951,36 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
948 | case SIOCADDTUNNEL: | 951 | case SIOCADDTUNNEL: |
949 | case SIOCCHGTUNNEL: | 952 | case SIOCCHGTUNNEL: |
950 | err = -EPERM; | 953 | err = -EPERM; |
951 | create = (cmd == SIOCADDTUNNEL); | ||
952 | if (!capable(CAP_NET_ADMIN)) | 954 | if (!capable(CAP_NET_ADMIN)) |
953 | break; | 955 | break; |
954 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) { | 956 | err = -EFAULT; |
955 | err = -EFAULT; | 957 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
956 | break; | 958 | break; |
957 | } | 959 | err = -EINVAL; |
958 | if (!create && dev != ip6ip6_fb_tnl_dev) { | 960 | if (p.proto != IPPROTO_IPV6) |
959 | t = netdev_priv(dev); | ||
960 | } | ||
961 | if (!t && (err = ip6ip6_tnl_locate(&p, &t, create))) { | ||
962 | break; | 961 | break; |
963 | } | 962 | t = ip6ip6_tnl_locate(&p, cmd == SIOCADDTUNNEL); |
964 | if (cmd == SIOCCHGTUNNEL) { | 963 | if (dev != ip6ip6_fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
965 | if (t->dev != dev) { | 964 | if (t != NULL) { |
966 | err = -EEXIST; | 965 | if (t->dev != dev) { |
967 | break; | 966 | err = -EEXIST; |
968 | } | 967 | break; |
968 | } | ||
969 | } else | ||
970 | t = netdev_priv(dev); | ||
971 | |||
969 | ip6ip6_tnl_unlink(t); | 972 | ip6ip6_tnl_unlink(t); |
970 | err = ip6ip6_tnl_change(t, &p); | 973 | err = ip6ip6_tnl_change(t, &p); |
971 | ip6ip6_tnl_link(t); | 974 | ip6ip6_tnl_link(t); |
972 | netdev_state_change(dev); | 975 | netdev_state_change(dev); |
973 | } | 976 | } |
974 | if (copy_to_user(ifr->ifr_ifru.ifru_data, | 977 | if (t) { |
975 | &t->parms, sizeof (p))) { | ||
976 | err = -EFAULT; | ||
977 | } else { | ||
978 | err = 0; | 978 | err = 0; |
979 | } | 979 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof (p))) |
980 | err = -EFAULT; | ||
981 | |||
982 | } else | ||
983 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | ||
980 | break; | 984 | break; |
981 | case SIOCDELTUNNEL: | 985 | case SIOCDELTUNNEL: |
982 | err = -EPERM; | 986 | err = -EPERM; |
@@ -984,22 +988,18 @@ ip6ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
984 | break; | 988 | break; |
985 | 989 | ||
986 | if (dev == ip6ip6_fb_tnl_dev) { | 990 | if (dev == ip6ip6_fb_tnl_dev) { |
987 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, | 991 | err = -EFAULT; |
988 | sizeof (p))) { | 992 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
989 | err = -EFAULT; | ||
990 | break; | 993 | break; |
991 | } | 994 | err = -ENOENT; |
992 | err = ip6ip6_tnl_locate(&p, &t, 0); | 995 | if ((t = ip6ip6_tnl_locate(&p, 0)) == NULL) |
993 | if (err) | ||
994 | break; | 996 | break; |
995 | if (t == netdev_priv(ip6ip6_fb_tnl_dev)) { | 997 | err = -EPERM; |
996 | err = -EPERM; | 998 | if (t->dev == ip6ip6_fb_tnl_dev) |
997 | break; | 999 | break; |
998 | } | 1000 | dev = t->dev; |
999 | } else { | ||
1000 | t = netdev_priv(dev); | ||
1001 | } | 1001 | } |
1002 | err = unregister_netdevice(t->dev); | 1002 | err = unregister_netdevice(dev); |
1003 | break; | 1003 | break; |
1004 | default: | 1004 | default: |
1005 | err = -EINVAL; | 1005 | err = -EINVAL; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 71f59f18ede8..511730b67e97 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -176,7 +176,7 @@ out_ok: | |||
176 | } | 176 | } |
177 | 177 | ||
178 | static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 178 | static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
179 | int type, int code, int offset, __u32 info) | 179 | int type, int code, int offset, __be32 info) |
180 | { | 180 | { |
181 | __be32 spi; | 181 | __be32 spi; |
182 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 182 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index de6b91981b30..1eafcfc95e81 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <net/inet_common.h> | 51 | #include <net/inet_common.h> |
52 | #include <net/tcp.h> | 52 | #include <net/tcp.h> |
53 | #include <net/udp.h> | 53 | #include <net/udp.h> |
54 | #include <net/udplite.h> | ||
54 | #include <net/xfrm.h> | 55 | #include <net/xfrm.h> |
55 | 56 | ||
56 | #include <asm/uaccess.h> | 57 | #include <asm/uaccess.h> |
@@ -239,6 +240,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
239 | struct sk_buff *pktopt; | 240 | struct sk_buff *pktopt; |
240 | 241 | ||
241 | if (sk->sk_protocol != IPPROTO_UDP && | 242 | if (sk->sk_protocol != IPPROTO_UDP && |
243 | sk->sk_protocol != IPPROTO_UDPLITE && | ||
242 | sk->sk_protocol != IPPROTO_TCP) | 244 | sk->sk_protocol != IPPROTO_TCP) |
243 | break; | 245 | break; |
244 | 246 | ||
@@ -276,11 +278,15 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
276 | sk->sk_family = PF_INET; | 278 | sk->sk_family = PF_INET; |
277 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); | 279 | tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); |
278 | } else { | 280 | } else { |
281 | struct proto *prot = &udp_prot; | ||
282 | |||
283 | if (sk->sk_protocol == IPPROTO_UDPLITE) | ||
284 | prot = &udplite_prot; | ||
279 | local_bh_disable(); | 285 | local_bh_disable(); |
280 | sock_prot_dec_use(sk->sk_prot); | 286 | sock_prot_dec_use(sk->sk_prot); |
281 | sock_prot_inc_use(&udp_prot); | 287 | sock_prot_inc_use(prot); |
282 | local_bh_enable(); | 288 | local_bh_enable(); |
283 | sk->sk_prot = &udp_prot; | 289 | sk->sk_prot = prot; |
284 | sk->sk_socket->ops = &inet_dgram_ops; | 290 | sk->sk_socket->ops = &inet_dgram_ops; |
285 | sk->sk_family = PF_INET; | 291 | sk->sk_family = PF_INET; |
286 | } | 292 | } |
@@ -813,6 +819,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
813 | switch (optname) { | 819 | switch (optname) { |
814 | case IPV6_ADDRFORM: | 820 | case IPV6_ADDRFORM: |
815 | if (sk->sk_protocol != IPPROTO_UDP && | 821 | if (sk->sk_protocol != IPPROTO_UDP && |
822 | sk->sk_protocol != IPPROTO_UDPLITE && | ||
816 | sk->sk_protocol != IPPROTO_TCP) | 823 | sk->sk_protocol != IPPROTO_TCP) |
817 | return -EINVAL; | 824 | return -EINVAL; |
818 | if (sk->sk_state != TCP_ESTABLISHED) | 825 | if (sk->sk_state != TCP_ESTABLISHED) |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3b114e3fa2f8..a1c231a04ac2 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -83,7 +83,7 @@ | |||
83 | struct mld2_grec { | 83 | struct mld2_grec { |
84 | __u8 grec_type; | 84 | __u8 grec_type; |
85 | __u8 grec_auxwords; | 85 | __u8 grec_auxwords; |
86 | __u16 grec_nsrcs; | 86 | __be16 grec_nsrcs; |
87 | struct in6_addr grec_mca; | 87 | struct in6_addr grec_mca; |
88 | struct in6_addr grec_src[0]; | 88 | struct in6_addr grec_src[0]; |
89 | }; | 89 | }; |
@@ -91,18 +91,18 @@ struct mld2_grec { | |||
91 | struct mld2_report { | 91 | struct mld2_report { |
92 | __u8 type; | 92 | __u8 type; |
93 | __u8 resv1; | 93 | __u8 resv1; |
94 | __u16 csum; | 94 | __sum16 csum; |
95 | __u16 resv2; | 95 | __be16 resv2; |
96 | __u16 ngrec; | 96 | __be16 ngrec; |
97 | struct mld2_grec grec[0]; | 97 | struct mld2_grec grec[0]; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | struct mld2_query { | 100 | struct mld2_query { |
101 | __u8 type; | 101 | __u8 type; |
102 | __u8 code; | 102 | __u8 code; |
103 | __u16 csum; | 103 | __sum16 csum; |
104 | __u16 mrc; | 104 | __be16 mrc; |
105 | __u16 resv1; | 105 | __be16 resv1; |
106 | struct in6_addr mca; | 106 | struct in6_addr mca; |
107 | #if defined(__LITTLE_ENDIAN_BITFIELD) | 107 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
108 | __u8 qrv:3, | 108 | __u8 qrv:3, |
@@ -116,7 +116,7 @@ struct mld2_query { | |||
116 | #error "Please fix <asm/byteorder.h>" | 116 | #error "Please fix <asm/byteorder.h>" |
117 | #endif | 117 | #endif |
118 | __u8 qqic; | 118 | __u8 qqic; |
119 | __u16 nsrcs; | 119 | __be16 nsrcs; |
120 | struct in6_addr srcs[0]; | 120 | struct in6_addr srcs[0]; |
121 | }; | 121 | }; |
122 | 122 | ||
@@ -1465,7 +1465,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1465 | struct inet6_dev *idev = in6_dev_get(skb->dev); | 1465 | struct inet6_dev *idev = in6_dev_get(skb->dev); |
1466 | int err; | 1466 | int err; |
1467 | 1467 | ||
1468 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1468 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
1469 | payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - | 1469 | payload_len = skb->tail - (unsigned char *)skb->nh.ipv6h - |
1470 | sizeof(struct ipv6hdr); | 1470 | sizeof(struct ipv6hdr); |
1471 | mldlen = skb->tail - skb->h.raw; | 1471 | mldlen = skb->tail - skb->h.raw; |
@@ -1477,9 +1477,9 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1477 | mld_dev_queue_xmit); | 1477 | mld_dev_queue_xmit); |
1478 | if (!err) { | 1478 | if (!err) { |
1479 | ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); | 1479 | ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); |
1480 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 1480 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
1481 | } else | 1481 | } else |
1482 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1482 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
1483 | 1483 | ||
1484 | if (likely(idev != NULL)) | 1484 | if (likely(idev != NULL)) |
1485 | in6_dev_put(idev); | 1485 | in6_dev_put(idev); |
@@ -1763,7 +1763,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1763 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1763 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1764 | IPV6_TLV_PADN, 0 }; | 1764 | IPV6_TLV_PADN, 0 }; |
1765 | 1765 | ||
1766 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1766 | rcu_read_lock(); |
1767 | IP6_INC_STATS(__in6_dev_get(dev), | ||
1768 | IPSTATS_MIB_OUTREQUESTS); | ||
1769 | rcu_read_unlock(); | ||
1767 | snd_addr = addr; | 1770 | snd_addr = addr; |
1768 | if (type == ICMPV6_MGM_REDUCTION) { | 1771 | if (type == ICMPV6_MGM_REDUCTION) { |
1769 | snd_addr = &all_routers; | 1772 | snd_addr = &all_routers; |
@@ -1777,7 +1780,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1777 | skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); | 1780 | skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); |
1778 | 1781 | ||
1779 | if (skb == NULL) { | 1782 | if (skb == NULL) { |
1780 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1783 | rcu_read_lock(); |
1784 | IP6_INC_STATS(__in6_dev_get(dev), | ||
1785 | IPSTATS_MIB_OUTDISCARDS); | ||
1786 | rcu_read_unlock(); | ||
1781 | return; | 1787 | return; |
1782 | } | 1788 | } |
1783 | 1789 | ||
@@ -1816,9 +1822,9 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) | |||
1816 | else | 1822 | else |
1817 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); | 1823 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBRESPONSES); |
1818 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); | 1824 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS); |
1819 | IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); | 1825 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTMCASTPKTS); |
1820 | } else | 1826 | } else |
1821 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 1827 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTDISCARDS); |
1822 | 1828 | ||
1823 | if (likely(idev != NULL)) | 1829 | if (likely(idev != NULL)) |
1824 | in6_dev_put(idev); | 1830 | in6_dev_put(idev); |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 7ccdc8fc5a31..be7dd7db65d7 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -262,10 +262,10 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct | |||
262 | sel.proto = fl->proto; | 262 | sel.proto = fl->proto; |
263 | sel.dport = xfrm_flowi_dport(fl); | 263 | sel.dport = xfrm_flowi_dport(fl); |
264 | if (sel.dport) | 264 | if (sel.dport) |
265 | sel.dport_mask = ~((__u16)0); | 265 | sel.dport_mask = htons(~0); |
266 | sel.sport = xfrm_flowi_sport(fl); | 266 | sel.sport = xfrm_flowi_sport(fl); |
267 | if (sel.sport) | 267 | if (sel.sport) |
268 | sel.sport_mask = ~((__u16)0); | 268 | sel.sport_mask = htons(~0); |
269 | sel.ifindex = fl->oif; | 269 | sel.ifindex = fl->oif; |
270 | 270 | ||
271 | err = km_report(IPPROTO_DSTOPTS, &sel, | 271 | err = km_report(IPPROTO_DSTOPTS, &sel, |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 73eb8c33e9f0..56ea92837307 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -472,7 +472,9 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
472 | inc_opt = 0; | 472 | inc_opt = 0; |
473 | } | 473 | } |
474 | 474 | ||
475 | skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), | 475 | skb = sock_alloc_send_skb(sk, |
476 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
477 | len + LL_RESERVED_SPACE(dev)), | ||
476 | 1, &err); | 478 | 1, &err); |
477 | 479 | ||
478 | if (skb == NULL) { | 480 | if (skb == NULL) { |
@@ -513,7 +515,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
513 | 515 | ||
514 | skb->dst = dst; | 516 | skb->dst = dst; |
515 | idev = in6_dev_get(dst->dev); | 517 | idev = in6_dev_get(dst->dev); |
516 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 518 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
517 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 519 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
518 | if (!err) { | 520 | if (!err) { |
519 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); | 521 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS); |
@@ -561,7 +563,9 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
561 | if (send_llinfo) | 563 | if (send_llinfo) |
562 | len += ndisc_opt_addr_space(dev); | 564 | len += ndisc_opt_addr_space(dev); |
563 | 565 | ||
564 | skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), | 566 | skb = sock_alloc_send_skb(sk, |
567 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
568 | len + LL_RESERVED_SPACE(dev)), | ||
565 | 1, &err); | 569 | 1, &err); |
566 | if (skb == NULL) { | 570 | if (skb == NULL) { |
567 | ND_PRINTK0(KERN_ERR | 571 | ND_PRINTK0(KERN_ERR |
@@ -597,7 +601,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
597 | /* send it! */ | 601 | /* send it! */ |
598 | skb->dst = dst; | 602 | skb->dst = dst; |
599 | idev = in6_dev_get(dst->dev); | 603 | idev = in6_dev_get(dst->dev); |
600 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 604 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
601 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 605 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
602 | if (!err) { | 606 | if (!err) { |
603 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); | 607 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTNEIGHBORSOLICITS); |
@@ -636,7 +640,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
636 | if (dev->addr_len) | 640 | if (dev->addr_len) |
637 | len += ndisc_opt_addr_space(dev); | 641 | len += ndisc_opt_addr_space(dev); |
638 | 642 | ||
639 | skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), | 643 | skb = sock_alloc_send_skb(sk, |
644 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
645 | len + LL_RESERVED_SPACE(dev)), | ||
640 | 1, &err); | 646 | 1, &err); |
641 | if (skb == NULL) { | 647 | if (skb == NULL) { |
642 | ND_PRINTK0(KERN_ERR | 648 | ND_PRINTK0(KERN_ERR |
@@ -670,7 +676,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
670 | /* send it! */ | 676 | /* send it! */ |
671 | skb->dst = dst; | 677 | skb->dst = dst; |
672 | idev = in6_dev_get(dst->dev); | 678 | idev = in6_dev_get(dst->dev); |
673 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 679 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
674 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); | 680 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, dst->dev, dst_output); |
675 | if (!err) { | 681 | if (!err) { |
676 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); | 682 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTROUTERSOLICITS); |
@@ -1261,10 +1267,11 @@ skip_defrtr: | |||
1261 | } | 1267 | } |
1262 | 1268 | ||
1263 | if (ndopts.nd_opts_mtu) { | 1269 | if (ndopts.nd_opts_mtu) { |
1270 | __be32 n; | ||
1264 | u32 mtu; | 1271 | u32 mtu; |
1265 | 1272 | ||
1266 | memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); | 1273 | memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); |
1267 | mtu = ntohl(mtu); | 1274 | mtu = ntohl(n); |
1268 | 1275 | ||
1269 | if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) { | 1276 | if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) { |
1270 | ND_PRINTK2(KERN_WARNING | 1277 | ND_PRINTK2(KERN_WARNING |
@@ -1446,7 +1453,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1446 | rd_len &= ~0x7; | 1453 | rd_len &= ~0x7; |
1447 | len += rd_len; | 1454 | len += rd_len; |
1448 | 1455 | ||
1449 | buff = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev), | 1456 | buff = sock_alloc_send_skb(sk, |
1457 | (MAX_HEADER + sizeof(struct ipv6hdr) + | ||
1458 | len + LL_RESERVED_SPACE(dev)), | ||
1450 | 1, &err); | 1459 | 1, &err); |
1451 | if (buff == NULL) { | 1460 | if (buff == NULL) { |
1452 | ND_PRINTK0(KERN_ERR | 1461 | ND_PRINTK0(KERN_ERR |
@@ -1504,7 +1513,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1504 | 1513 | ||
1505 | buff->dst = dst; | 1514 | buff->dst = dst; |
1506 | idev = in6_dev_get(dst->dev); | 1515 | idev = in6_dev_get(dst->dev); |
1507 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 1516 | IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS); |
1508 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); | 1517 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, buff, NULL, dst->dev, dst_output); |
1509 | if (!err) { | 1518 | if (!err) { |
1510 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); | 1519 | ICMP6_INC_STATS(idev, ICMP6_MIB_OUTREDIRECTS); |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 580b1aba6722..f6294e5bcb31 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -31,7 +31,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
31 | #endif | 31 | #endif |
32 | 32 | ||
33 | if (dst->error) { | 33 | if (dst->error) { |
34 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 34 | IP6_INC_STATS(ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); |
35 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); | 35 | LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); |
36 | dst_release(dst); | 36 | dst_release(dst); |
37 | return -EINVAL; | 37 | return -EINVAL; |
@@ -80,11 +80,11 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) | |||
80 | return 0; | 80 | return 0; |
81 | } | 81 | } |
82 | 82 | ||
83 | unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | 83 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
84 | unsigned int dataoff, u_int8_t protocol) | 84 | unsigned int dataoff, u_int8_t protocol) |
85 | { | 85 | { |
86 | struct ipv6hdr *ip6h = skb->nh.ipv6h; | 86 | struct ipv6hdr *ip6h = skb->nh.ipv6h; |
87 | unsigned int csum = 0; | 87 | __sum16 csum = 0; |
88 | 88 | ||
89 | switch (skb->ip_summed) { | 89 | switch (skb->ip_summed) { |
90 | case CHECKSUM_COMPLETE: | 90 | case CHECKSUM_COMPLETE: |
@@ -100,12 +100,13 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | |||
100 | } | 100 | } |
101 | /* fall through */ | 101 | /* fall through */ |
102 | case CHECKSUM_NONE: | 102 | case CHECKSUM_NONE: |
103 | skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | 103 | skb->csum = ~csum_unfold( |
104 | csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | ||
104 | skb->len - dataoff, | 105 | skb->len - dataoff, |
105 | protocol, | 106 | protocol, |
106 | csum_sub(0, | 107 | csum_sub(0, |
107 | skb_checksum(skb, 0, | 108 | skb_checksum(skb, 0, |
108 | dataoff, 0))); | 109 | dataoff, 0)))); |
109 | csum = __skb_checksum_complete(skb); | 110 | csum = __skb_checksum_complete(skb); |
110 | } | 111 | } |
111 | return csum; | 112 | return csum; |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index d7c45a9c15fe..fc3e5eb4bc3f 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -6,7 +6,7 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" | |||
6 | depends on INET && IPV6 && NETFILTER && EXPERIMENTAL | 6 | depends on INET && IPV6 && NETFILTER && EXPERIMENTAL |
7 | 7 | ||
8 | config NF_CONNTRACK_IPV6 | 8 | config NF_CONNTRACK_IPV6 |
9 | tristate "IPv6 support for new connection tracking (EXPERIMENTAL)" | 9 | tristate "IPv6 connection tracking support (EXPERIMENTAL)" |
10 | depends on EXPERIMENTAL && NF_CONNTRACK | 10 | depends on EXPERIMENTAL && NF_CONNTRACK |
11 | ---help--- | 11 | ---help--- |
12 | Connection tracking keeps a record of what packets have passed | 12 | Connection tracking keeps a record of what packets have passed |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9fec832ee08b..d4d9f182441a 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
@@ -241,7 +241,7 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | |||
241 | pmsg->data_len = data_len; | 241 | pmsg->data_len = data_len; |
242 | pmsg->timestamp_sec = entry->skb->tstamp.off_sec; | 242 | pmsg->timestamp_sec = entry->skb->tstamp.off_sec; |
243 | pmsg->timestamp_usec = entry->skb->tstamp.off_usec; | 243 | pmsg->timestamp_usec = entry->skb->tstamp.off_usec; |
244 | pmsg->mark = entry->skb->nfmark; | 244 | pmsg->mark = entry->skb->mark; |
245 | pmsg->hook = entry->info->hook; | 245 | pmsg->hook = entry->info->hook; |
246 | pmsg->hw_protocol = entry->skb->protocol; | 246 | pmsg->hw_protocol = entry->skb->protocol; |
247 | 247 | ||
@@ -620,6 +620,7 @@ static ctl_table ipq_root_table[] = { | |||
620 | { .ctl_name = 0 } | 620 | { .ctl_name = 0 } |
621 | }; | 621 | }; |
622 | 622 | ||
623 | #ifdef CONFIG_PROC_FS | ||
623 | static int | 624 | static int |
624 | ipq_get_info(char *buffer, char **start, off_t offset, int length) | 625 | ipq_get_info(char *buffer, char **start, off_t offset, int length) |
625 | { | 626 | { |
@@ -653,6 +654,7 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length) | |||
653 | len = 0; | 654 | len = 0; |
654 | return len; | 655 | return len; |
655 | } | 656 | } |
657 | #endif /* CONFIG_PROC_FS */ | ||
656 | 658 | ||
657 | static struct nf_queue_handler nfqh = { | 659 | static struct nf_queue_handler nfqh = { |
658 | .name = "ip6_queue", | 660 | .name = "ip6_queue", |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 204e02162d49..f63fb86d7c7b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1481,7 +1481,8 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
1481 | if (hp == NULL) | 1481 | if (hp == NULL) |
1482 | return -EBADMSG; | 1482 | return -EBADMSG; |
1483 | if (nexthdr == NEXTHDR_FRAGMENT) { | 1483 | if (nexthdr == NEXTHDR_FRAGMENT) { |
1484 | unsigned short _frag_off, *fp; | 1484 | unsigned short _frag_off; |
1485 | __be16 *fp; | ||
1485 | fp = skb_header_pointer(skb, | 1486 | fp = skb_header_pointer(skb, |
1486 | start+offsetof(struct frag_hdr, | 1487 | start+offsetof(struct frag_hdr, |
1487 | frag_off), | 1488 | frag_off), |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 0cf537d30185..33b1faa90d74 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -69,9 +69,9 @@ static void dump_packet(const struct nf_loginfo *info, | |||
69 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | 69 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ |
70 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | 70 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", |
71 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | 71 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), |
72 | (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20, | 72 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, |
73 | ih->hop_limit, | 73 | ih->hop_limit, |
74 | (ntohl(*(u_int32_t *)ih) & 0x000fffff)); | 74 | (ntohl(*(__be32 *)ih) & 0x000fffff)); |
75 | 75 | ||
76 | fragment = 0; | 76 | fragment = 0; |
77 | ptr = ip6hoff + sizeof(struct ipv6hdr); | 77 | ptr = ip6hoff + sizeof(struct ipv6hdr); |
@@ -270,11 +270,15 @@ static void dump_packet(const struct nf_loginfo *info, | |||
270 | } | 270 | } |
271 | break; | 271 | break; |
272 | } | 272 | } |
273 | case IPPROTO_UDP: { | 273 | case IPPROTO_UDP: |
274 | case IPPROTO_UDPLITE: { | ||
274 | struct udphdr _udph, *uh; | 275 | struct udphdr _udph, *uh; |
275 | 276 | ||
276 | /* Max length: 10 "PROTO=UDP " */ | 277 | if (currenthdr == IPPROTO_UDP) |
277 | printk("PROTO=UDP "); | 278 | /* Max length: 10 "PROTO=UDP " */ |
279 | printk("PROTO=UDP " ); | ||
280 | else /* Max length: 14 "PROTO=UDPLITE " */ | ||
281 | printk("PROTO=UDPLITE "); | ||
278 | 282 | ||
279 | if (fragment) | 283 | if (fragment) |
280 | break; | 284 | break; |
@@ -436,13 +440,8 @@ ip6t_log_target(struct sk_buff **pskb, | |||
436 | li.u.log.level = loginfo->level; | 440 | li.u.log.level = loginfo->level; |
437 | li.u.log.logflags = loginfo->logflags; | 441 | li.u.log.logflags = loginfo->logflags; |
438 | 442 | ||
439 | if (loginfo->logflags & IP6T_LOG_NFLOG) | 443 | ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, |
440 | nf_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, | 444 | loginfo->prefix); |
441 | "%s", loginfo->prefix); | ||
442 | else | ||
443 | ip6t_log_packet(PF_INET6, hooknum, *pskb, in, out, &li, | ||
444 | loginfo->prefix); | ||
445 | |||
446 | return IP6T_CONTINUE; | 445 | return IP6T_CONTINUE; |
447 | } | 446 | } |
448 | 447 | ||
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 386ea260e767..6250e86a6ddc 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -149,11 +149,10 @@ ip6t_local_hook(unsigned int hook, | |||
149 | int (*okfn)(struct sk_buff *)) | 149 | int (*okfn)(struct sk_buff *)) |
150 | { | 150 | { |
151 | 151 | ||
152 | unsigned long nfmark; | ||
153 | unsigned int ret; | 152 | unsigned int ret; |
154 | struct in6_addr saddr, daddr; | 153 | struct in6_addr saddr, daddr; |
155 | u_int8_t hop_limit; | 154 | u_int8_t hop_limit; |
156 | u_int32_t flowlabel; | 155 | u_int32_t flowlabel, mark; |
157 | 156 | ||
158 | #if 0 | 157 | #if 0 |
159 | /* root is playing with raw sockets. */ | 158 | /* root is playing with raw sockets. */ |
@@ -165,10 +164,10 @@ ip6t_local_hook(unsigned int hook, | |||
165 | } | 164 | } |
166 | #endif | 165 | #endif |
167 | 166 | ||
168 | /* save source/dest address, nfmark, hoplimit, flowlabel, priority, */ | 167 | /* save source/dest address, mark, hoplimit, flowlabel, priority, */ |
169 | memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); | 168 | memcpy(&saddr, &(*pskb)->nh.ipv6h->saddr, sizeof(saddr)); |
170 | memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); | 169 | memcpy(&daddr, &(*pskb)->nh.ipv6h->daddr, sizeof(daddr)); |
171 | nfmark = (*pskb)->nfmark; | 170 | mark = (*pskb)->mark; |
172 | hop_limit = (*pskb)->nh.ipv6h->hop_limit; | 171 | hop_limit = (*pskb)->nh.ipv6h->hop_limit; |
173 | 172 | ||
174 | /* flowlabel and prio (includes version, which shouldn't change either */ | 173 | /* flowlabel and prio (includes version, which shouldn't change either */ |
@@ -179,7 +178,7 @@ ip6t_local_hook(unsigned int hook, | |||
179 | if (ret != NF_DROP && ret != NF_STOLEN | 178 | if (ret != NF_DROP && ret != NF_STOLEN |
180 | && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) | 179 | && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) |
181 | || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) | 180 | || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) |
182 | || (*pskb)->nfmark != nfmark | 181 | || (*pskb)->mark != mark |
183 | || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) | 182 | || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) |
184 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; | 183 | return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; |
185 | 184 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e5e53fff9e38..a20615ffccff 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/netfilter_ipv6.h> | 33 | #include <linux/netfilter_ipv6.h> |
34 | #include <net/netfilter/nf_conntrack.h> | 34 | #include <net/netfilter/nf_conntrack.h> |
35 | #include <net/netfilter/nf_conntrack_helper.h> | 35 | #include <net/netfilter/nf_conntrack_helper.h> |
36 | #include <net/netfilter/nf_conntrack_protocol.h> | 36 | #include <net/netfilter/nf_conntrack_l4proto.h> |
37 | #include <net/netfilter/nf_conntrack_l3proto.h> | 37 | #include <net/netfilter/nf_conntrack_l3proto.h> |
38 | #include <net/netfilter/nf_conntrack_core.h> | 38 | #include <net/netfilter/nf_conntrack_core.h> |
39 | 39 | ||
@@ -43,8 +43,6 @@ | |||
43 | #define DEBUGP(format, args...) | 43 | #define DEBUGP(format, args...) |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | DECLARE_PER_CPU(struct ip_conntrack_stat, nf_conntrack_stat); | ||
47 | |||
48 | static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 46 | static int ipv6_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
49 | struct nf_conntrack_tuple *tuple) | 47 | struct nf_conntrack_tuple *tuple) |
50 | { | 48 | { |
@@ -211,11 +209,6 @@ out: | |||
211 | return nf_conntrack_confirm(pskb); | 209 | return nf_conntrack_confirm(pskb); |
212 | } | 210 | } |
213 | 211 | ||
214 | extern struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb); | ||
215 | extern void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | ||
216 | struct net_device *in, | ||
217 | struct net_device *out, | ||
218 | int (*okfn)(struct sk_buff *)); | ||
219 | static unsigned int ipv6_defrag(unsigned int hooknum, | 212 | static unsigned int ipv6_defrag(unsigned int hooknum, |
220 | struct sk_buff **pskb, | 213 | struct sk_buff **pskb, |
221 | const struct net_device *in, | 214 | const struct net_device *in, |
@@ -331,26 +324,7 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { | |||
331 | }; | 324 | }; |
332 | 325 | ||
333 | #ifdef CONFIG_SYSCTL | 326 | #ifdef CONFIG_SYSCTL |
334 | 327 | static ctl_table nf_ct_ipv6_sysctl_table[] = { | |
335 | /* From nf_conntrack_proto_icmpv6.c */ | ||
336 | extern unsigned int nf_ct_icmpv6_timeout; | ||
337 | |||
338 | /* From nf_conntrack_reasm.c */ | ||
339 | extern unsigned int nf_ct_frag6_timeout; | ||
340 | extern unsigned int nf_ct_frag6_low_thresh; | ||
341 | extern unsigned int nf_ct_frag6_high_thresh; | ||
342 | |||
343 | static struct ctl_table_header *nf_ct_ipv6_sysctl_header; | ||
344 | |||
345 | static ctl_table nf_ct_sysctl_table[] = { | ||
346 | { | ||
347 | .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT, | ||
348 | .procname = "nf_conntrack_icmpv6_timeout", | ||
349 | .data = &nf_ct_icmpv6_timeout, | ||
350 | .maxlen = sizeof(unsigned int), | ||
351 | .mode = 0644, | ||
352 | .proc_handler = &proc_dointvec_jiffies, | ||
353 | }, | ||
354 | { | 328 | { |
355 | .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, | 329 | .ctl_name = NET_NF_CONNTRACK_FRAG6_TIMEOUT, |
356 | .procname = "nf_conntrack_frag6_timeout", | 330 | .procname = "nf_conntrack_frag6_timeout", |
@@ -377,26 +351,6 @@ static ctl_table nf_ct_sysctl_table[] = { | |||
377 | }, | 351 | }, |
378 | { .ctl_name = 0 } | 352 | { .ctl_name = 0 } |
379 | }; | 353 | }; |
380 | |||
381 | static ctl_table nf_ct_netfilter_table[] = { | ||
382 | { | ||
383 | .ctl_name = NET_NETFILTER, | ||
384 | .procname = "netfilter", | ||
385 | .mode = 0555, | ||
386 | .child = nf_ct_sysctl_table, | ||
387 | }, | ||
388 | { .ctl_name = 0 } | ||
389 | }; | ||
390 | |||
391 | static ctl_table nf_ct_net_table[] = { | ||
392 | { | ||
393 | .ctl_name = CTL_NET, | ||
394 | .procname = "net", | ||
395 | .mode = 0555, | ||
396 | .child = nf_ct_netfilter_table, | ||
397 | }, | ||
398 | { .ctl_name = 0 } | ||
399 | }; | ||
400 | #endif | 354 | #endif |
401 | 355 | ||
402 | #if defined(CONFIG_NF_CT_NETLINK) || \ | 356 | #if defined(CONFIG_NF_CT_NETLINK) || \ |
@@ -454,16 +408,14 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 = { | |||
454 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, | 408 | .tuple_to_nfattr = ipv6_tuple_to_nfattr, |
455 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, | 409 | .nfattr_to_tuple = ipv6_nfattr_to_tuple, |
456 | #endif | 410 | #endif |
411 | #ifdef CONFIG_SYSCTL | ||
412 | .ctl_table_path = nf_net_netfilter_sysctl_path, | ||
413 | .ctl_table = nf_ct_ipv6_sysctl_table, | ||
414 | #endif | ||
457 | .get_features = ipv6_get_features, | 415 | .get_features = ipv6_get_features, |
458 | .me = THIS_MODULE, | 416 | .me = THIS_MODULE, |
459 | }; | 417 | }; |
460 | 418 | ||
461 | extern struct nf_conntrack_protocol nf_conntrack_protocol_tcp6; | ||
462 | extern struct nf_conntrack_protocol nf_conntrack_protocol_udp6; | ||
463 | extern struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6; | ||
464 | extern int nf_ct_frag6_init(void); | ||
465 | extern void nf_ct_frag6_cleanup(void); | ||
466 | |||
467 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); | 419 | MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6)); |
468 | MODULE_LICENSE("GPL"); | 420 | MODULE_LICENSE("GPL"); |
469 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | 421 | MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); |
@@ -479,19 +431,19 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
479 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); | 431 | printk("nf_conntrack_ipv6: can't initialize frag6.\n"); |
480 | return ret; | 432 | return ret; |
481 | } | 433 | } |
482 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_tcp6); | 434 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_tcp6); |
483 | if (ret < 0) { | 435 | if (ret < 0) { |
484 | printk("nf_conntrack_ipv6: can't register tcp.\n"); | 436 | printk("nf_conntrack_ipv6: can't register tcp.\n"); |
485 | goto cleanup_frag6; | 437 | goto cleanup_frag6; |
486 | } | 438 | } |
487 | 439 | ||
488 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_udp6); | 440 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_udp6); |
489 | if (ret < 0) { | 441 | if (ret < 0) { |
490 | printk("nf_conntrack_ipv6: can't register udp.\n"); | 442 | printk("nf_conntrack_ipv6: can't register udp.\n"); |
491 | goto cleanup_tcp; | 443 | goto cleanup_tcp; |
492 | } | 444 | } |
493 | 445 | ||
494 | ret = nf_conntrack_protocol_register(&nf_conntrack_protocol_icmpv6); | 446 | ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_icmpv6); |
495 | if (ret < 0) { | 447 | if (ret < 0) { |
496 | printk("nf_conntrack_ipv6: can't register icmpv6.\n"); | 448 | printk("nf_conntrack_ipv6: can't register icmpv6.\n"); |
497 | goto cleanup_udp; | 449 | goto cleanup_udp; |
@@ -510,28 +462,16 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
510 | "hook.\n"); | 462 | "hook.\n"); |
511 | goto cleanup_ipv6; | 463 | goto cleanup_ipv6; |
512 | } | 464 | } |
513 | #ifdef CONFIG_SYSCTL | ||
514 | nf_ct_ipv6_sysctl_header = register_sysctl_table(nf_ct_net_table, 0); | ||
515 | if (nf_ct_ipv6_sysctl_header == NULL) { | ||
516 | printk("nf_conntrack: can't register to sysctl.\n"); | ||
517 | ret = -ENOMEM; | ||
518 | goto cleanup_hooks; | ||
519 | } | ||
520 | #endif | ||
521 | return ret; | 465 | return ret; |
522 | 466 | ||
523 | #ifdef CONFIG_SYSCTL | ||
524 | cleanup_hooks: | ||
525 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); | ||
526 | #endif | ||
527 | cleanup_ipv6: | 467 | cleanup_ipv6: |
528 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); | 468 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); |
529 | cleanup_icmpv6: | 469 | cleanup_icmpv6: |
530 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); | 470 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); |
531 | cleanup_udp: | 471 | cleanup_udp: |
532 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); | 472 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); |
533 | cleanup_tcp: | 473 | cleanup_tcp: |
534 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); | 474 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); |
535 | cleanup_frag6: | 475 | cleanup_frag6: |
536 | nf_ct_frag6_cleanup(); | 476 | nf_ct_frag6_cleanup(); |
537 | return ret; | 477 | return ret; |
@@ -540,14 +480,11 @@ static int __init nf_conntrack_l3proto_ipv6_init(void) | |||
540 | static void __exit nf_conntrack_l3proto_ipv6_fini(void) | 480 | static void __exit nf_conntrack_l3proto_ipv6_fini(void) |
541 | { | 481 | { |
542 | synchronize_net(); | 482 | synchronize_net(); |
543 | #ifdef CONFIG_SYSCTL | ||
544 | unregister_sysctl_table(nf_ct_ipv6_sysctl_header); | ||
545 | #endif | ||
546 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); | 483 | nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops)); |
547 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); | 484 | nf_conntrack_l3proto_unregister(&nf_conntrack_l3proto_ipv6); |
548 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_icmpv6); | 485 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_icmpv6); |
549 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_udp6); | 486 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_udp6); |
550 | nf_conntrack_protocol_unregister(&nf_conntrack_protocol_tcp6); | 487 | nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_tcp6); |
551 | nf_ct_frag6_cleanup(); | 488 | nf_ct_frag6_cleanup(); |
552 | } | 489 | } |
553 | 490 | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 34d447208ffd..3905cacc69af 100644 --- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c | |||
@@ -29,11 +29,11 @@ | |||
29 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
30 | #include <linux/netfilter_ipv6.h> | 30 | #include <linux/netfilter_ipv6.h> |
31 | #include <net/netfilter/nf_conntrack_tuple.h> | 31 | #include <net/netfilter/nf_conntrack_tuple.h> |
32 | #include <net/netfilter/nf_conntrack_protocol.h> | 32 | #include <net/netfilter/nf_conntrack_l4proto.h> |
33 | #include <net/netfilter/nf_conntrack_core.h> | 33 | #include <net/netfilter/nf_conntrack_core.h> |
34 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> | 34 | #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> |
35 | 35 | ||
36 | unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; | 36 | static unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; |
37 | 37 | ||
38 | #if 0 | 38 | #if 0 |
39 | #define DEBUGP printk | 39 | #define DEBUGP printk |
@@ -142,9 +142,6 @@ static int icmpv6_new(struct nf_conn *conntrack, | |||
142 | return 1; | 142 | return 1; |
143 | } | 143 | } |
144 | 144 | ||
145 | extern int | ||
146 | nf_ct_ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len); | ||
147 | extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; | ||
148 | static int | 145 | static int |
149 | icmpv6_error_message(struct sk_buff *skb, | 146 | icmpv6_error_message(struct sk_buff *skb, |
150 | unsigned int icmp6off, | 147 | unsigned int icmp6off, |
@@ -155,7 +152,7 @@ icmpv6_error_message(struct sk_buff *skb, | |||
155 | struct nf_conntrack_tuple_hash *h; | 152 | struct nf_conntrack_tuple_hash *h; |
156 | struct icmp6hdr _hdr, *hp; | 153 | struct icmp6hdr _hdr, *hp; |
157 | unsigned int inip6off; | 154 | unsigned int inip6off; |
158 | struct nf_conntrack_protocol *inproto; | 155 | struct nf_conntrack_l4proto *inproto; |
159 | u_int8_t inprotonum; | 156 | u_int8_t inprotonum; |
160 | unsigned int inprotoff; | 157 | unsigned int inprotoff; |
161 | 158 | ||
@@ -185,7 +182,7 @@ icmpv6_error_message(struct sk_buff *skb, | |||
185 | return -NF_ACCEPT; | 182 | return -NF_ACCEPT; |
186 | } | 183 | } |
187 | 184 | ||
188 | inproto = __nf_ct_proto_find(PF_INET6, inprotonum); | 185 | inproto = __nf_ct_l4proto_find(PF_INET6, inprotonum); |
189 | 186 | ||
190 | /* Are they talking about one of our connections? */ | 187 | /* Are they talking about one of our connections? */ |
191 | if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, | 188 | if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum, |
@@ -290,7 +287,7 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[], | |||
290 | tuple->dst.u.icmp.code = | 287 | tuple->dst.u.icmp.code = |
291 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]); | 288 | *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_CODE-1]); |
292 | tuple->src.u.icmp.id = | 289 | tuple->src.u.icmp.id = |
293 | *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]); | 290 | *(__be16 *)NFA_DATA(tb[CTA_PROTO_ICMPV6_ID-1]); |
294 | 291 | ||
295 | if (tuple->dst.u.icmp.type < 128 | 292 | if (tuple->dst.u.icmp.type < 128 |
296 | || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) | 293 | || tuple->dst.u.icmp.type - 128 >= sizeof(invmap) |
@@ -301,10 +298,27 @@ static int icmpv6_nfattr_to_tuple(struct nfattr *tb[], | |||
301 | } | 298 | } |
302 | #endif | 299 | #endif |
303 | 300 | ||
304 | struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 = | 301 | #ifdef CONFIG_SYSCTL |
302 | static struct ctl_table_header *icmpv6_sysctl_header; | ||
303 | static struct ctl_table icmpv6_sysctl_table[] = { | ||
304 | { | ||
305 | .ctl_name = NET_NF_CONNTRACK_ICMPV6_TIMEOUT, | ||
306 | .procname = "nf_conntrack_icmpv6_timeout", | ||
307 | .data = &nf_ct_icmpv6_timeout, | ||
308 | .maxlen = sizeof(unsigned int), | ||
309 | .mode = 0644, | ||
310 | .proc_handler = &proc_dointvec_jiffies, | ||
311 | }, | ||
312 | { | ||
313 | .ctl_name = 0 | ||
314 | } | ||
315 | }; | ||
316 | #endif /* CONFIG_SYSCTL */ | ||
317 | |||
318 | struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = | ||
305 | { | 319 | { |
306 | .l3proto = PF_INET6, | 320 | .l3proto = PF_INET6, |
307 | .proto = IPPROTO_ICMPV6, | 321 | .l4proto = IPPROTO_ICMPV6, |
308 | .name = "icmpv6", | 322 | .name = "icmpv6", |
309 | .pkt_to_tuple = icmpv6_pkt_to_tuple, | 323 | .pkt_to_tuple = icmpv6_pkt_to_tuple, |
310 | .invert_tuple = icmpv6_invert_tuple, | 324 | .invert_tuple = icmpv6_invert_tuple, |
@@ -318,6 +332,10 @@ struct nf_conntrack_protocol nf_conntrack_protocol_icmpv6 = | |||
318 | .tuple_to_nfattr = icmpv6_tuple_to_nfattr, | 332 | .tuple_to_nfattr = icmpv6_tuple_to_nfattr, |
319 | .nfattr_to_tuple = icmpv6_nfattr_to_tuple, | 333 | .nfattr_to_tuple = icmpv6_nfattr_to_tuple, |
320 | #endif | 334 | #endif |
335 | #ifdef CONFIG_SYSCTL | ||
336 | .ctl_table_header = &icmpv6_sysctl_header, | ||
337 | .ctl_table = icmpv6_sysctl_table, | ||
338 | #endif | ||
321 | }; | 339 | }; |
322 | 340 | ||
323 | EXPORT_SYMBOL(nf_conntrack_protocol_icmpv6); | 341 | EXPORT_SYMBOL(nf_conntrack_l4proto_icmpv6); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index bf93c1ea6be9..37e5fca923aa 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -72,7 +72,7 @@ struct nf_ct_frag6_queue | |||
72 | struct hlist_node list; | 72 | struct hlist_node list; |
73 | struct list_head lru_list; /* lru list member */ | 73 | struct list_head lru_list; /* lru list member */ |
74 | 74 | ||
75 | __u32 id; /* fragment id */ | 75 | __be32 id; /* fragment id */ |
76 | struct in6_addr saddr; | 76 | struct in6_addr saddr; |
77 | struct in6_addr daddr; | 77 | struct in6_addr daddr; |
78 | 78 | ||
@@ -115,28 +115,28 @@ static __inline__ void fq_unlink(struct nf_ct_frag6_queue *fq) | |||
115 | write_unlock(&nf_ct_frag6_lock); | 115 | write_unlock(&nf_ct_frag6_lock); |
116 | } | 116 | } |
117 | 117 | ||
118 | static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, | 118 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, |
119 | struct in6_addr *daddr) | 119 | struct in6_addr *daddr) |
120 | { | 120 | { |
121 | u32 a, b, c; | 121 | u32 a, b, c; |
122 | 122 | ||
123 | a = saddr->s6_addr32[0]; | 123 | a = (__force u32)saddr->s6_addr32[0]; |
124 | b = saddr->s6_addr32[1]; | 124 | b = (__force u32)saddr->s6_addr32[1]; |
125 | c = saddr->s6_addr32[2]; | 125 | c = (__force u32)saddr->s6_addr32[2]; |
126 | 126 | ||
127 | a += JHASH_GOLDEN_RATIO; | 127 | a += JHASH_GOLDEN_RATIO; |
128 | b += JHASH_GOLDEN_RATIO; | 128 | b += JHASH_GOLDEN_RATIO; |
129 | c += nf_ct_frag6_hash_rnd; | 129 | c += nf_ct_frag6_hash_rnd; |
130 | __jhash_mix(a, b, c); | 130 | __jhash_mix(a, b, c); |
131 | 131 | ||
132 | a += saddr->s6_addr32[3]; | 132 | a += (__force u32)saddr->s6_addr32[3]; |
133 | b += daddr->s6_addr32[0]; | 133 | b += (__force u32)daddr->s6_addr32[0]; |
134 | c += daddr->s6_addr32[1]; | 134 | c += (__force u32)daddr->s6_addr32[1]; |
135 | __jhash_mix(a, b, c); | 135 | __jhash_mix(a, b, c); |
136 | 136 | ||
137 | a += daddr->s6_addr32[2]; | 137 | a += (__force u32)daddr->s6_addr32[2]; |
138 | b += daddr->s6_addr32[3]; | 138 | b += (__force u32)daddr->s6_addr32[3]; |
139 | c += id; | 139 | c += (__force u32)id; |
140 | __jhash_mix(a, b, c); | 140 | __jhash_mix(a, b, c); |
141 | 141 | ||
142 | return c & (FRAG6Q_HASHSZ - 1); | 142 | return c & (FRAG6Q_HASHSZ - 1); |
@@ -338,7 +338,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | |||
338 | 338 | ||
339 | 339 | ||
340 | static struct nf_ct_frag6_queue * | 340 | static struct nf_ct_frag6_queue * |
341 | nf_ct_frag6_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst) | 341 | nf_ct_frag6_create(unsigned int hash, __be32 id, struct in6_addr *src, struct in6_addr *dst) |
342 | { | 342 | { |
343 | struct nf_ct_frag6_queue *fq; | 343 | struct nf_ct_frag6_queue *fq; |
344 | 344 | ||
@@ -366,7 +366,7 @@ oom: | |||
366 | } | 366 | } |
367 | 367 | ||
368 | static __inline__ struct nf_ct_frag6_queue * | 368 | static __inline__ struct nf_ct_frag6_queue * |
369 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 369 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) |
370 | { | 370 | { |
371 | struct nf_ct_frag6_queue *fq; | 371 | struct nf_ct_frag6_queue *fq; |
372 | struct hlist_node *n; | 372 | struct hlist_node *n; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index efee7a6301a8..35249d8487bb 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -49,6 +49,8 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
49 | fold_prot_inuse(&tcpv6_prot)); | 49 | fold_prot_inuse(&tcpv6_prot)); |
50 | seq_printf(seq, "UDP6: inuse %d\n", | 50 | seq_printf(seq, "UDP6: inuse %d\n", |
51 | fold_prot_inuse(&udpv6_prot)); | 51 | fold_prot_inuse(&udpv6_prot)); |
52 | seq_printf(seq, "UDPLITE6: inuse %d\n", | ||
53 | fold_prot_inuse(&udplitev6_prot)); | ||
52 | seq_printf(seq, "RAW6: inuse %d\n", | 54 | seq_printf(seq, "RAW6: inuse %d\n", |
53 | fold_prot_inuse(&rawv6_prot)); | 55 | fold_prot_inuse(&rawv6_prot)); |
54 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 56 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", |
@@ -133,6 +135,14 @@ static struct snmp_mib snmp6_udp6_list[] = { | |||
133 | SNMP_MIB_SENTINEL | 135 | SNMP_MIB_SENTINEL |
134 | }; | 136 | }; |
135 | 137 | ||
138 | static struct snmp_mib snmp6_udplite6_list[] = { | ||
139 | SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS), | ||
140 | SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS), | ||
141 | SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS), | ||
142 | SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS), | ||
143 | SNMP_MIB_SENTINEL | ||
144 | }; | ||
145 | |||
136 | static unsigned long | 146 | static unsigned long |
137 | fold_field(void *mib[], int offt) | 147 | fold_field(void *mib[], int offt) |
138 | { | 148 | { |
@@ -161,11 +171,13 @@ static int snmp6_seq_show(struct seq_file *seq, void *v) | |||
161 | 171 | ||
162 | if (idev) { | 172 | if (idev) { |
163 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); | 173 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); |
174 | snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); | ||
164 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); | 175 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); |
165 | } else { | 176 | } else { |
166 | snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); | 177 | snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); |
167 | snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); | 178 | snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); |
168 | snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); | 179 | snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); |
180 | snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list); | ||
169 | } | 181 | } |
170 | return 0; | 182 | return 0; |
171 | } | 183 | } |
@@ -281,6 +293,9 @@ int snmp6_alloc_dev(struct inet6_dev *idev) | |||
281 | if (!idev || !idev->dev) | 293 | if (!idev || !idev->dev) |
282 | return -EINVAL; | 294 | return -EINVAL; |
283 | 295 | ||
296 | if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib), | ||
297 | __alignof__(struct ipstats_mib)) < 0) | ||
298 | goto err_ip; | ||
284 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), | 299 | if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), |
285 | __alignof__(struct icmpv6_mib)) < 0) | 300 | __alignof__(struct icmpv6_mib)) < 0) |
286 | goto err_icmp; | 301 | goto err_icmp; |
@@ -288,12 +303,15 @@ int snmp6_alloc_dev(struct inet6_dev *idev) | |||
288 | return 0; | 303 | return 0; |
289 | 304 | ||
290 | err_icmp: | 305 | err_icmp: |
306 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
307 | err_ip: | ||
291 | return err; | 308 | return err; |
292 | } | 309 | } |
293 | 310 | ||
294 | int snmp6_free_dev(struct inet6_dev *idev) | 311 | int snmp6_free_dev(struct inet6_dev *idev) |
295 | { | 312 | { |
296 | snmp6_mib_free((void **)idev->stats.icmpv6); | 313 | snmp6_mib_free((void **)idev->stats.icmpv6); |
314 | snmp6_mib_free((void **)idev->stats.ipv6); | ||
297 | return 0; | 315 | return 0; |
298 | } | 316 | } |
299 | 317 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index d6dedc4aec77..c2e629d6aea4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -220,7 +220,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
220 | struct inet_sock *inet = inet_sk(sk); | 220 | struct inet_sock *inet = inet_sk(sk); |
221 | struct ipv6_pinfo *np = inet6_sk(sk); | 221 | struct ipv6_pinfo *np = inet6_sk(sk); |
222 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; | 222 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; |
223 | __u32 v4addr = 0; | 223 | __be32 v4addr = 0; |
224 | int addr_type; | 224 | int addr_type; |
225 | int err; | 225 | int err; |
226 | 226 | ||
@@ -290,7 +290,7 @@ out: | |||
290 | 290 | ||
291 | void rawv6_err(struct sock *sk, struct sk_buff *skb, | 291 | void rawv6_err(struct sock *sk, struct sk_buff *skb, |
292 | struct inet6_skb_parm *opt, | 292 | struct inet6_skb_parm *opt, |
293 | int type, int code, int offset, u32 info) | 293 | int type, int code, int offset, __be32 info) |
294 | { | 294 | { |
295 | struct inet_sock *inet = inet_sk(sk); | 295 | struct inet_sock *inet = inet_sk(sk); |
296 | struct ipv6_pinfo *np = inet6_sk(sk); | 296 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -370,9 +370,9 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) | |||
370 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 370 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
371 | } | 371 | } |
372 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 372 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) |
373 | skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 373 | skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, |
374 | &skb->nh.ipv6h->daddr, | 374 | &skb->nh.ipv6h->daddr, |
375 | skb->len, inet->num, 0); | 375 | skb->len, inet->num, 0)); |
376 | 376 | ||
377 | if (inet->hdrincl) { | 377 | if (inet->hdrincl) { |
378 | if (skb_checksum_complete(skb)) { | 378 | if (skb_checksum_complete(skb)) { |
@@ -479,8 +479,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
479 | int offset; | 479 | int offset; |
480 | int len; | 480 | int len; |
481 | int total_len; | 481 | int total_len; |
482 | u32 tmp_csum; | 482 | __wsum tmp_csum; |
483 | u16 csum; | 483 | __sum16 csum; |
484 | 484 | ||
485 | if (!rp->checksum) | 485 | if (!rp->checksum) |
486 | goto send; | 486 | goto send; |
@@ -530,16 +530,15 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, | |||
530 | 530 | ||
531 | /* in case cksum was not initialized */ | 531 | /* in case cksum was not initialized */ |
532 | if (unlikely(csum)) | 532 | if (unlikely(csum)) |
533 | tmp_csum = csum_sub(tmp_csum, csum); | 533 | tmp_csum = csum_sub(tmp_csum, csum_unfold(csum)); |
534 | 534 | ||
535 | tmp_csum = csum_ipv6_magic(&fl->fl6_src, | 535 | csum = csum_ipv6_magic(&fl->fl6_src, |
536 | &fl->fl6_dst, | 536 | &fl->fl6_dst, |
537 | total_len, fl->proto, tmp_csum); | 537 | total_len, fl->proto, tmp_csum); |
538 | 538 | ||
539 | if (tmp_csum == 0) | 539 | if (csum == 0 && fl->proto == IPPROTO_UDP) |
540 | tmp_csum = -1; | 540 | csum = CSUM_MANGLED_0; |
541 | 541 | ||
542 | csum = tmp_csum; | ||
543 | if (skb_store_bits(skb, offset, &csum, 2)) | 542 | if (skb_store_bits(skb, offset, &csum, 2)) |
544 | BUG(); | 543 | BUG(); |
545 | 544 | ||
@@ -586,7 +585,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, | |||
586 | if (err) | 585 | if (err) |
587 | goto error_fault; | 586 | goto error_fault; |
588 | 587 | ||
589 | IP6_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 588 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS); |
590 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, | 589 | err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev, |
591 | dst_output); | 590 | dst_output); |
592 | if (err > 0) | 591 | if (err > 0) |
@@ -600,7 +599,7 @@ error_fault: | |||
600 | err = -EFAULT; | 599 | err = -EFAULT; |
601 | kfree_skb(skb); | 600 | kfree_skb(skb); |
602 | error: | 601 | error: |
603 | IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); | 602 | IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); |
604 | return err; | 603 | return err; |
605 | } | 604 | } |
606 | 605 | ||
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index f39bbedd1327..6f9a9046510f 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <net/snmp.h> | 47 | #include <net/snmp.h> |
48 | 48 | ||
49 | #include <net/ipv6.h> | 49 | #include <net/ipv6.h> |
50 | #include <net/ip6_route.h> | ||
50 | #include <net/protocol.h> | 51 | #include <net/protocol.h> |
51 | #include <net/transp_v6.h> | 52 | #include <net/transp_v6.h> |
52 | #include <net/rawv6.h> | 53 | #include <net/rawv6.h> |
@@ -76,7 +77,7 @@ struct frag_queue | |||
76 | struct hlist_node list; | 77 | struct hlist_node list; |
77 | struct list_head lru_list; /* lru list member */ | 78 | struct list_head lru_list; /* lru list member */ |
78 | 79 | ||
79 | __u32 id; /* fragment id */ | 80 | __be32 id; /* fragment id */ |
80 | struct in6_addr saddr; | 81 | struct in6_addr saddr; |
81 | struct in6_addr daddr; | 82 | struct in6_addr daddr; |
82 | 83 | ||
@@ -124,28 +125,28 @@ static __inline__ void fq_unlink(struct frag_queue *fq) | |||
124 | * callers should be careful not to use the hash value outside the ipfrag_lock | 125 | * callers should be careful not to use the hash value outside the ipfrag_lock |
125 | * as doing so could race with ipfrag_hash_rnd being recalculated. | 126 | * as doing so could race with ipfrag_hash_rnd being recalculated. |
126 | */ | 127 | */ |
127 | static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, | 128 | static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, |
128 | struct in6_addr *daddr) | 129 | struct in6_addr *daddr) |
129 | { | 130 | { |
130 | u32 a, b, c; | 131 | u32 a, b, c; |
131 | 132 | ||
132 | a = saddr->s6_addr32[0]; | 133 | a = (__force u32)saddr->s6_addr32[0]; |
133 | b = saddr->s6_addr32[1]; | 134 | b = (__force u32)saddr->s6_addr32[1]; |
134 | c = saddr->s6_addr32[2]; | 135 | c = (__force u32)saddr->s6_addr32[2]; |
135 | 136 | ||
136 | a += JHASH_GOLDEN_RATIO; | 137 | a += JHASH_GOLDEN_RATIO; |
137 | b += JHASH_GOLDEN_RATIO; | 138 | b += JHASH_GOLDEN_RATIO; |
138 | c += ip6_frag_hash_rnd; | 139 | c += ip6_frag_hash_rnd; |
139 | __jhash_mix(a, b, c); | 140 | __jhash_mix(a, b, c); |
140 | 141 | ||
141 | a += saddr->s6_addr32[3]; | 142 | a += (__force u32)saddr->s6_addr32[3]; |
142 | b += daddr->s6_addr32[0]; | 143 | b += (__force u32)daddr->s6_addr32[0]; |
143 | c += daddr->s6_addr32[1]; | 144 | c += (__force u32)daddr->s6_addr32[1]; |
144 | __jhash_mix(a, b, c); | 145 | __jhash_mix(a, b, c); |
145 | 146 | ||
146 | a += daddr->s6_addr32[2]; | 147 | a += (__force u32)daddr->s6_addr32[2]; |
147 | b += daddr->s6_addr32[3]; | 148 | b += (__force u32)daddr->s6_addr32[3]; |
148 | c += id; | 149 | c += (__force u32)id; |
149 | __jhash_mix(a, b, c); | 150 | __jhash_mix(a, b, c); |
150 | 151 | ||
151 | return c & (IP6Q_HASHSZ - 1); | 152 | return c & (IP6Q_HASHSZ - 1); |
@@ -257,7 +258,7 @@ static __inline__ void fq_kill(struct frag_queue *fq) | |||
257 | } | 258 | } |
258 | } | 259 | } |
259 | 260 | ||
260 | static void ip6_evictor(void) | 261 | static void ip6_evictor(struct inet6_dev *idev) |
261 | { | 262 | { |
262 | struct frag_queue *fq; | 263 | struct frag_queue *fq; |
263 | struct list_head *tmp; | 264 | struct list_head *tmp; |
@@ -284,14 +285,14 @@ static void ip6_evictor(void) | |||
284 | spin_unlock(&fq->lock); | 285 | spin_unlock(&fq->lock); |
285 | 286 | ||
286 | fq_put(fq, &work); | 287 | fq_put(fq, &work); |
287 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 288 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); |
288 | } | 289 | } |
289 | } | 290 | } |
290 | 291 | ||
291 | static void ip6_frag_expire(unsigned long data) | 292 | static void ip6_frag_expire(unsigned long data) |
292 | { | 293 | { |
293 | struct frag_queue *fq = (struct frag_queue *) data; | 294 | struct frag_queue *fq = (struct frag_queue *) data; |
294 | struct net_device *dev; | 295 | struct net_device *dev = NULL; |
295 | 296 | ||
296 | spin_lock(&fq->lock); | 297 | spin_lock(&fq->lock); |
297 | 298 | ||
@@ -300,17 +301,19 @@ static void ip6_frag_expire(unsigned long data) | |||
300 | 301 | ||
301 | fq_kill(fq); | 302 | fq_kill(fq); |
302 | 303 | ||
303 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMTIMEOUT); | 304 | dev = dev_get_by_index(fq->iif); |
304 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 305 | if (!dev) |
306 | goto out; | ||
307 | |||
308 | rcu_read_lock(); | ||
309 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
310 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | ||
311 | rcu_read_unlock(); | ||
305 | 312 | ||
306 | /* Don't send error if the first segment did not arrive. */ | 313 | /* Don't send error if the first segment did not arrive. */ |
307 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) | 314 | if (!(fq->last_in&FIRST_IN) || !fq->fragments) |
308 | goto out; | 315 | goto out; |
309 | 316 | ||
310 | dev = dev_get_by_index(fq->iif); | ||
311 | if (!dev) | ||
312 | goto out; | ||
313 | |||
314 | /* | 317 | /* |
315 | But use as source device on which LAST ARRIVED | 318 | But use as source device on which LAST ARRIVED |
316 | segment was received. And do not use fq->dev | 319 | segment was received. And do not use fq->dev |
@@ -318,8 +321,9 @@ static void ip6_frag_expire(unsigned long data) | |||
318 | */ | 321 | */ |
319 | fq->fragments->dev = dev; | 322 | fq->fragments->dev = dev; |
320 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 323 | icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
321 | dev_put(dev); | ||
322 | out: | 324 | out: |
325 | if (dev) | ||
326 | dev_put(dev); | ||
323 | spin_unlock(&fq->lock); | 327 | spin_unlock(&fq->lock); |
324 | fq_put(fq, NULL); | 328 | fq_put(fq, NULL); |
325 | } | 329 | } |
@@ -366,7 +370,8 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) | |||
366 | 370 | ||
367 | 371 | ||
368 | static struct frag_queue * | 372 | static struct frag_queue * |
369 | ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) | 373 | ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst, |
374 | struct inet6_dev *idev) | ||
370 | { | 375 | { |
371 | struct frag_queue *fq; | 376 | struct frag_queue *fq; |
372 | 377 | ||
@@ -386,12 +391,13 @@ ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst) | |||
386 | return ip6_frag_intern(fq); | 391 | return ip6_frag_intern(fq); |
387 | 392 | ||
388 | oom: | 393 | oom: |
389 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 394 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); |
390 | return NULL; | 395 | return NULL; |
391 | } | 396 | } |
392 | 397 | ||
393 | static __inline__ struct frag_queue * | 398 | static __inline__ struct frag_queue * |
394 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 399 | fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, |
400 | struct inet6_dev *idev) | ||
395 | { | 401 | { |
396 | struct frag_queue *fq; | 402 | struct frag_queue *fq; |
397 | struct hlist_node *n; | 403 | struct hlist_node *n; |
@@ -410,7 +416,7 @@ fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | |||
410 | } | 416 | } |
411 | read_unlock(&ip6_frag_lock); | 417 | read_unlock(&ip6_frag_lock); |
412 | 418 | ||
413 | return ip6_frag_create(id, src, dst); | 419 | return ip6_frag_create(id, src, dst, idev); |
414 | } | 420 | } |
415 | 421 | ||
416 | 422 | ||
@@ -428,7 +434,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
428 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); | 434 | ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); |
429 | 435 | ||
430 | if ((unsigned int)end > IPV6_MAXPLEN) { | 436 | if ((unsigned int)end > IPV6_MAXPLEN) { |
431 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 437 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
438 | IPSTATS_MIB_INHDRERRORS); | ||
432 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); | 439 | icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off - skb->nh.raw); |
433 | return; | 440 | return; |
434 | } | 441 | } |
@@ -455,7 +462,8 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
455 | /* RFC2460 says always send parameter problem in | 462 | /* RFC2460 says always send parameter problem in |
456 | * this case. -DaveM | 463 | * this case. -DaveM |
457 | */ | 464 | */ |
458 | IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); | 465 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), |
466 | IPSTATS_MIB_INHDRERRORS); | ||
459 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, | 467 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, |
460 | offsetof(struct ipv6hdr, payload_len)); | 468 | offsetof(struct ipv6hdr, payload_len)); |
461 | return; | 469 | return; |
@@ -571,7 +579,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
571 | return; | 579 | return; |
572 | 580 | ||
573 | err: | 581 | err: |
574 | IP6_INC_STATS(IPSTATS_MIB_REASMFAILS); | 582 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
575 | kfree_skb(skb); | 583 | kfree_skb(skb); |
576 | } | 584 | } |
577 | 585 | ||
@@ -665,7 +673,9 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, | |||
665 | if (head->ip_summed == CHECKSUM_COMPLETE) | 673 | if (head->ip_summed == CHECKSUM_COMPLETE) |
666 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); | 674 | head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); |
667 | 675 | ||
668 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 676 | rcu_read_lock(); |
677 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMOKS); | ||
678 | rcu_read_unlock(); | ||
669 | fq->fragments = NULL; | 679 | fq->fragments = NULL; |
670 | return 1; | 680 | return 1; |
671 | 681 | ||
@@ -677,7 +687,9 @@ out_oom: | |||
677 | if (net_ratelimit()) | 687 | if (net_ratelimit()) |
678 | printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); | 688 | printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); |
679 | out_fail: | 689 | out_fail: |
680 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 690 | rcu_read_lock(); |
691 | IP6_INC_STATS_BH(__in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | ||
692 | rcu_read_unlock(); | ||
681 | return -1; | 693 | return -1; |
682 | } | 694 | } |
683 | 695 | ||
@@ -691,16 +703,16 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
691 | 703 | ||
692 | hdr = skb->nh.ipv6h; | 704 | hdr = skb->nh.ipv6h; |
693 | 705 | ||
694 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMREQDS); | 706 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMREQDS); |
695 | 707 | ||
696 | /* Jumbo payload inhibits frag. header */ | 708 | /* Jumbo payload inhibits frag. header */ |
697 | if (hdr->payload_len==0) { | 709 | if (hdr->payload_len==0) { |
698 | IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); | 710 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
699 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 711 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); |
700 | return -1; | 712 | return -1; |
701 | } | 713 | } |
702 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { | 714 | if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { |
703 | IP6_INC_STATS(IPSTATS_MIB_INHDRERRORS); | 715 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); |
704 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); | 716 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); |
705 | return -1; | 717 | return -1; |
706 | } | 718 | } |
@@ -711,16 +723,17 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
711 | if (!(fhdr->frag_off & htons(0xFFF9))) { | 723 | if (!(fhdr->frag_off & htons(0xFFF9))) { |
712 | /* It is not a fragmented frame */ | 724 | /* It is not a fragmented frame */ |
713 | skb->h.raw += sizeof(struct frag_hdr); | 725 | skb->h.raw += sizeof(struct frag_hdr); |
714 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); | 726 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMOKS); |
715 | 727 | ||
716 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; | 728 | IP6CB(skb)->nhoff = (u8*)fhdr - skb->nh.raw; |
717 | return 1; | 729 | return 1; |
718 | } | 730 | } |
719 | 731 | ||
720 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) | 732 | if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) |
721 | ip6_evictor(); | 733 | ip6_evictor(ip6_dst_idev(skb->dst)); |
722 | 734 | ||
723 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) { | 735 | if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr, |
736 | ip6_dst_idev(skb->dst))) != NULL) { | ||
724 | int ret = -1; | 737 | int ret = -1; |
725 | 738 | ||
726 | spin_lock(&fq->lock); | 739 | spin_lock(&fq->lock); |
@@ -736,7 +749,7 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) | |||
736 | return ret; | 749 | return ret; |
737 | } | 750 | } |
738 | 751 | ||
739 | IP6_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | 752 | IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_REASMFAILS); |
740 | kfree_skb(skb); | 753 | kfree_skb(skb); |
741 | return -1; | 754 | return -1; |
742 | } | 755 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index b39ae99122d5..9f80518aacbd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -440,7 +440,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
440 | if (pref == ICMPV6_ROUTER_PREF_INVALID) | 440 | if (pref == ICMPV6_ROUTER_PREF_INVALID) |
441 | pref = ICMPV6_ROUTER_PREF_MEDIUM; | 441 | pref = ICMPV6_ROUTER_PREF_MEDIUM; |
442 | 442 | ||
443 | lifetime = htonl(rinfo->lifetime); | 443 | lifetime = ntohl(rinfo->lifetime); |
444 | if (lifetime == 0xffffffff) { | 444 | if (lifetime == 0xffffffff) { |
445 | /* infinity */ | 445 | /* infinity */ |
446 | } else if (lifetime > 0x7fffffff/HZ) { | 446 | } else if (lifetime > 0x7fffffff/HZ) { |
@@ -711,12 +711,10 @@ void ip6_route_input(struct sk_buff *skb) | |||
711 | .ip6_u = { | 711 | .ip6_u = { |
712 | .daddr = iph->daddr, | 712 | .daddr = iph->daddr, |
713 | .saddr = iph->saddr, | 713 | .saddr = iph->saddr, |
714 | #ifdef CONFIG_IPV6_ROUTE_FWMARK | 714 | .flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK, |
715 | .fwmark = skb->nfmark, | ||
716 | #endif | ||
717 | .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, | ||
718 | }, | 715 | }, |
719 | }, | 716 | }, |
717 | .mark = skb->mark, | ||
720 | .proto = iph->nexthdr, | 718 | .proto = iph->nexthdr, |
721 | }; | 719 | }; |
722 | 720 | ||
@@ -942,7 +940,7 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, | |||
942 | fib6_force_start_gc(); | 940 | fib6_force_start_gc(); |
943 | 941 | ||
944 | out: | 942 | out: |
945 | return (struct dst_entry *)rt; | 943 | return &rt->u.dst; |
946 | } | 944 | } |
947 | 945 | ||
948 | int ndisc_dst_gc(int *more) | 946 | int ndisc_dst_gc(int *more) |
@@ -1225,7 +1223,7 @@ out: | |||
1225 | if (idev) | 1223 | if (idev) |
1226 | in6_dev_put(idev); | 1224 | in6_dev_put(idev); |
1227 | if (rt) | 1225 | if (rt) |
1228 | dst_free((struct dst_entry *) rt); | 1226 | dst_free(&rt->u.dst); |
1229 | return err; | 1227 | return err; |
1230 | } | 1228 | } |
1231 | 1229 | ||
@@ -1751,9 +1749,9 @@ static inline int ip6_pkt_drop(struct sk_buff *skb, int code) | |||
1751 | { | 1749 | { |
1752 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); | 1750 | int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); |
1753 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) | 1751 | if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) |
1754 | IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); | 1752 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_INADDRERRORS); |
1755 | 1753 | ||
1756 | IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); | 1754 | IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTNOROUTES); |
1757 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); | 1755 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0, skb->dev); |
1758 | kfree_skb(skb); | 1756 | kfree_skb(skb); |
1759 | return 0; | 1757 | return 0; |
@@ -1824,7 +1822,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1824 | rt->rt6i_flags |= RTF_LOCAL; | 1822 | rt->rt6i_flags |= RTF_LOCAL; |
1825 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1823 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
1826 | if (rt->rt6i_nexthop == NULL) { | 1824 | if (rt->rt6i_nexthop == NULL) { |
1827 | dst_free((struct dst_entry *) rt); | 1825 | dst_free(&rt->u.dst); |
1828 | return ERR_PTR(-ENOMEM); | 1826 | return ERR_PTR(-ENOMEM); |
1829 | } | 1827 | } |
1830 | 1828 | ||
@@ -2008,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
2008 | return ip6_route_add(&cfg); | 2006 | return ip6_route_add(&cfg); |
2009 | } | 2007 | } |
2010 | 2008 | ||
2009 | static inline size_t rt6_nlmsg_size(void) | ||
2010 | { | ||
2011 | return NLMSG_ALIGN(sizeof(struct rtmsg)) | ||
2012 | + nla_total_size(16) /* RTA_SRC */ | ||
2013 | + nla_total_size(16) /* RTA_DST */ | ||
2014 | + nla_total_size(16) /* RTA_GATEWAY */ | ||
2015 | + nla_total_size(16) /* RTA_PREFSRC */ | ||
2016 | + nla_total_size(4) /* RTA_TABLE */ | ||
2017 | + nla_total_size(4) /* RTA_IIF */ | ||
2018 | + nla_total_size(4) /* RTA_OIF */ | ||
2019 | + nla_total_size(4) /* RTA_PRIORITY */ | ||
2020 | + nla_total_size(sizeof(struct rta_cacheinfo)); | ||
2021 | } | ||
2022 | |||
2011 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | 2023 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, |
2012 | struct in6_addr *dst, struct in6_addr *src, | 2024 | struct in6_addr *dst, struct in6_addr *src, |
2013 | int iif, int type, u32 pid, u32 seq, | 2025 | int iif, int type, u32 pid, u32 seq, |
@@ -2015,7 +2027,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2015 | { | 2027 | { |
2016 | struct rtmsg *rtm; | 2028 | struct rtmsg *rtm; |
2017 | struct nlmsghdr *nlh; | 2029 | struct nlmsghdr *nlh; |
2018 | struct rta_cacheinfo ci; | 2030 | long expires; |
2019 | u32 table; | 2031 | u32 table; |
2020 | 2032 | ||
2021 | if (prefix) { /* user wants prefix routes only */ | 2033 | if (prefix) { /* user wants prefix routes only */ |
@@ -2089,18 +2101,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2089 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); | 2101 | NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); |
2090 | 2102 | ||
2091 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2103 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
2092 | ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); | 2104 | |
2093 | if (rt->rt6i_expires) | 2105 | expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0; |
2094 | ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); | 2106 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, |
2095 | else | 2107 | expires, rt->u.dst.error) < 0) |
2096 | ci.rta_expires = 0; | 2108 | goto nla_put_failure; |
2097 | ci.rta_used = rt->u.dst.__use; | ||
2098 | ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); | ||
2099 | ci.rta_error = rt->u.dst.error; | ||
2100 | ci.rta_id = 0; | ||
2101 | ci.rta_ts = 0; | ||
2102 | ci.rta_tsage = 0; | ||
2103 | NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); | ||
2104 | 2109 | ||
2105 | return nlmsg_end(skb, nlh); | 2110 | return nlmsg_end(skb, nlh); |
2106 | 2111 | ||
@@ -2202,7 +2207,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2202 | struct sk_buff *skb; | 2207 | struct sk_buff *skb; |
2203 | u32 pid = 0, seq = 0; | 2208 | u32 pid = 0, seq = 0; |
2204 | struct nlmsghdr *nlh = NULL; | 2209 | struct nlmsghdr *nlh = NULL; |
2205 | int payload = sizeof(struct rtmsg) + 256; | ||
2206 | int err = -ENOBUFS; | 2210 | int err = -ENOBUFS; |
2207 | 2211 | ||
2208 | if (info) { | 2212 | if (info) { |
@@ -2212,15 +2216,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2212 | seq = nlh->nlmsg_seq; | 2216 | seq = nlh->nlmsg_seq; |
2213 | } | 2217 | } |
2214 | 2218 | ||
2215 | skb = nlmsg_new(nlmsg_total_size(payload), gfp_any()); | 2219 | skb = nlmsg_new(rt6_nlmsg_size(), gfp_any()); |
2216 | if (skb == NULL) | 2220 | if (skb == NULL) |
2217 | goto errout; | 2221 | goto errout; |
2218 | 2222 | ||
2219 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); | 2223 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); |
2220 | if (err < 0) { | 2224 | /* failure implies BUG in rt6_nlmsg_size() */ |
2221 | kfree_skb(skb); | 2225 | BUG_ON(err < 0); |
2222 | goto errout; | ||
2223 | } | ||
2224 | 2226 | ||
2225 | err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); | 2227 | err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); |
2226 | errout: | 2228 | errout: |
@@ -2248,7 +2250,6 @@ struct rt6_proc_arg | |||
2248 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) | 2250 | static int rt6_info_route(struct rt6_info *rt, void *p_arg) |
2249 | { | 2251 | { |
2250 | struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg; | 2252 | struct rt6_proc_arg *arg = (struct rt6_proc_arg *) p_arg; |
2251 | int i; | ||
2252 | 2253 | ||
2253 | if (arg->skip < arg->offset / RT6_INFO_LEN) { | 2254 | if (arg->skip < arg->offset / RT6_INFO_LEN) { |
2254 | arg->skip++; | 2255 | arg->skip++; |
@@ -2258,38 +2259,28 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2258 | if (arg->len >= arg->length) | 2259 | if (arg->len >= arg->length) |
2259 | return 0; | 2260 | return 0; |
2260 | 2261 | ||
2261 | for (i=0; i<16; i++) { | 2262 | arg->len += sprintf(arg->buffer + arg->len, |
2262 | sprintf(arg->buffer + arg->len, "%02x", | 2263 | NIP6_SEQFMT " %02x ", |
2263 | rt->rt6i_dst.addr.s6_addr[i]); | 2264 | NIP6(rt->rt6i_dst.addr), |
2264 | arg->len += 2; | ||
2265 | } | ||
2266 | arg->len += sprintf(arg->buffer + arg->len, " %02x ", | ||
2267 | rt->rt6i_dst.plen); | 2265 | rt->rt6i_dst.plen); |
2268 | 2266 | ||
2269 | #ifdef CONFIG_IPV6_SUBTREES | 2267 | #ifdef CONFIG_IPV6_SUBTREES |
2270 | for (i=0; i<16; i++) { | 2268 | arg->len += sprintf(arg->buffer + arg->len, |
2271 | sprintf(arg->buffer + arg->len, "%02x", | 2269 | NIP6_SEQFMT " %02x ", |
2272 | rt->rt6i_src.addr.s6_addr[i]); | 2270 | NIP6(rt->rt6i_src.addr), |
2273 | arg->len += 2; | ||
2274 | } | ||
2275 | arg->len += sprintf(arg->buffer + arg->len, " %02x ", | ||
2276 | rt->rt6i_src.plen); | 2271 | rt->rt6i_src.plen); |
2277 | #else | 2272 | #else |
2278 | sprintf(arg->buffer + arg->len, | 2273 | arg->len += sprintf(arg->buffer + arg->len, |
2279 | "00000000000000000000000000000000 00 "); | 2274 | "00000000000000000000000000000000 00 "); |
2280 | arg->len += 36; | ||
2281 | #endif | 2275 | #endif |
2282 | 2276 | ||
2283 | if (rt->rt6i_nexthop) { | 2277 | if (rt->rt6i_nexthop) { |
2284 | for (i=0; i<16; i++) { | 2278 | arg->len += sprintf(arg->buffer + arg->len, |
2285 | sprintf(arg->buffer + arg->len, "%02x", | 2279 | NIP6_SEQFMT, |
2286 | rt->rt6i_nexthop->primary_key[i]); | 2280 | NIP6(*((struct in6_addr *)rt->rt6i_nexthop->primary_key))); |
2287 | arg->len += 2; | ||
2288 | } | ||
2289 | } else { | 2281 | } else { |
2290 | sprintf(arg->buffer + arg->len, | 2282 | arg->len += sprintf(arg->buffer + arg->len, |
2291 | "00000000000000000000000000000000"); | 2283 | "00000000000000000000000000000000"); |
2292 | arg->len += 32; | ||
2293 | } | 2284 | } |
2294 | arg->len += sprintf(arg->buffer + arg->len, | 2285 | arg->len += sprintf(arg->buffer + arg->len, |
2295 | " %08x %08x %08x %08x %8s\n", | 2286 | " %08x %08x %08x %08x %8s\n", |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index be699f85b2c7..77b7b0911438 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -60,7 +60,7 @@ | |||
60 | */ | 60 | */ |
61 | 61 | ||
62 | #define HASH_SIZE 16 | 62 | #define HASH_SIZE 16 |
63 | #define HASH(addr) ((addr^(addr>>4))&0xF) | 63 | #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) |
64 | 64 | ||
65 | static int ipip6_fb_tunnel_init(struct net_device *dev); | 65 | static int ipip6_fb_tunnel_init(struct net_device *dev); |
66 | static int ipip6_tunnel_init(struct net_device *dev); | 66 | static int ipip6_tunnel_init(struct net_device *dev); |
@@ -76,7 +76,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne | |||
76 | 76 | ||
77 | static DEFINE_RWLOCK(ipip6_lock); | 77 | static DEFINE_RWLOCK(ipip6_lock); |
78 | 78 | ||
79 | static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) | 79 | static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) |
80 | { | 80 | { |
81 | unsigned h0 = HASH(remote); | 81 | unsigned h0 = HASH(remote); |
82 | unsigned h1 = HASH(local); | 82 | unsigned h1 = HASH(local); |
@@ -102,8 +102,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) | |||
102 | 102 | ||
103 | static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) | 103 | static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) |
104 | { | 104 | { |
105 | u32 remote = t->parms.iph.daddr; | 105 | __be32 remote = t->parms.iph.daddr; |
106 | u32 local = t->parms.iph.saddr; | 106 | __be32 local = t->parms.iph.saddr; |
107 | unsigned h = 0; | 107 | unsigned h = 0; |
108 | int prio = 0; | 108 | int prio = 0; |
109 | 109 | ||
@@ -144,8 +144,8 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) | |||
144 | 144 | ||
145 | static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) | 145 | static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) |
146 | { | 146 | { |
147 | u32 remote = parms->iph.daddr; | 147 | __be32 remote = parms->iph.daddr; |
148 | u32 local = parms->iph.saddr; | 148 | __be32 local = parms->iph.saddr; |
149 | struct ip_tunnel *t, **tp, *nt; | 149 | struct ip_tunnel *t, **tp, *nt; |
150 | struct net_device *dev; | 150 | struct net_device *dev; |
151 | unsigned h = 0; | 151 | unsigned h = 0; |
@@ -405,9 +405,9 @@ out: | |||
405 | /* Returns the embedded IPv4 address if the IPv6 address | 405 | /* Returns the embedded IPv4 address if the IPv6 address |
406 | comes from 6to4 (RFC 3056) addr space */ | 406 | comes from 6to4 (RFC 3056) addr space */ |
407 | 407 | ||
408 | static inline u32 try_6to4(struct in6_addr *v6dst) | 408 | static inline __be32 try_6to4(struct in6_addr *v6dst) |
409 | { | 409 | { |
410 | u32 dst = 0; | 410 | __be32 dst = 0; |
411 | 411 | ||
412 | if (v6dst->s6_addr16[0] == htons(0x2002)) { | 412 | if (v6dst->s6_addr16[0] == htons(0x2002)) { |
413 | /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ | 413 | /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ |
@@ -432,7 +432,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
432 | struct net_device *tdev; /* Device to other host */ | 432 | struct net_device *tdev; /* Device to other host */ |
433 | struct iphdr *iph; /* Our new IP header */ | 433 | struct iphdr *iph; /* Our new IP header */ |
434 | int max_headroom; /* The extra header space needed */ | 434 | int max_headroom; /* The extra header space needed */ |
435 | u32 dst = tiph->daddr; | 435 | __be32 dst = tiph->daddr; |
436 | int mtu; | 436 | int mtu; |
437 | struct in6_addr *addr6; | 437 | struct in6_addr *addr6; |
438 | int addr_type; | 438 | int addr_type; |
@@ -809,7 +809,7 @@ static void __exit sit_destroy_tunnels(void) | |||
809 | } | 809 | } |
810 | } | 810 | } |
811 | 811 | ||
812 | void __exit sit_cleanup(void) | 812 | static void __exit sit_cleanup(void) |
813 | { | 813 | { |
814 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); | 814 | inet_del_protocol(&sit_protocol, IPPROTO_IPV6); |
815 | 815 | ||
@@ -819,7 +819,7 @@ void __exit sit_cleanup(void) | |||
819 | rtnl_unlock(); | 819 | rtnl_unlock(); |
820 | } | 820 | } |
821 | 821 | ||
822 | int __init sit_init(void) | 822 | static int __init sit_init(void) |
823 | { | 823 | { |
824 | int err; | 824 | int err; |
825 | 825 | ||
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4c2a7c0cafef..c25e930c2c69 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -66,10 +66,13 @@ | |||
66 | #include <linux/proc_fs.h> | 66 | #include <linux/proc_fs.h> |
67 | #include <linux/seq_file.h> | 67 | #include <linux/seq_file.h> |
68 | 68 | ||
69 | #include <linux/crypto.h> | ||
70 | #include <linux/scatterlist.h> | ||
71 | |||
69 | /* Socket used for sending RSTs and ACKs */ | 72 | /* Socket used for sending RSTs and ACKs */ |
70 | static struct socket *tcp6_socket; | 73 | static struct socket *tcp6_socket; |
71 | 74 | ||
72 | static void tcp_v6_send_reset(struct sk_buff *skb); | 75 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
73 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); | 76 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); |
74 | static void tcp_v6_send_check(struct sock *sk, int len, | 77 | static void tcp_v6_send_check(struct sock *sk, int len, |
75 | struct sk_buff *skb); | 78 | struct sk_buff *skb); |
@@ -78,6 +81,10 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | |||
78 | 81 | ||
79 | static struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static struct inet_connection_sock_af_ops ipv6_mapped; |
80 | static struct inet_connection_sock_af_ops ipv6_specific; | 83 | static struct inet_connection_sock_af_ops ipv6_specific; |
84 | #ifdef CONFIG_TCP_MD5SIG | ||
85 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; | ||
86 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | ||
87 | #endif | ||
81 | 88 | ||
82 | static int tcp_v6_get_port(struct sock *sk, unsigned short snum) | 89 | static int tcp_v6_get_port(struct sock *sk, unsigned short snum) |
83 | { | 90 | { |
@@ -98,27 +105,20 @@ static void tcp_v6_hash(struct sock *sk) | |||
98 | } | 105 | } |
99 | } | 106 | } |
100 | 107 | ||
101 | static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, | 108 | static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len, |
102 | struct in6_addr *saddr, | 109 | struct in6_addr *saddr, |
103 | struct in6_addr *daddr, | 110 | struct in6_addr *daddr, |
104 | unsigned long base) | 111 | __wsum base) |
105 | { | 112 | { |
106 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); | 113 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); |
107 | } | 114 | } |
108 | 115 | ||
109 | static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) | 116 | static __u32 tcp_v6_init_sequence(struct sk_buff *skb) |
110 | { | 117 | { |
111 | if (skb->protocol == htons(ETH_P_IPV6)) { | 118 | return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, |
112 | return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, | 119 | skb->nh.ipv6h->saddr.s6_addr32, |
113 | skb->nh.ipv6h->saddr.s6_addr32, | 120 | skb->h.th->dest, |
114 | skb->h.th->dest, | 121 | skb->h.th->source); |
115 | skb->h.th->source); | ||
116 | } else { | ||
117 | return secure_tcp_sequence_number(skb->nh.iph->daddr, | ||
118 | skb->nh.iph->saddr, | ||
119 | skb->h.th->dest, | ||
120 | skb->h.th->source); | ||
121 | } | ||
122 | } | 122 | } |
123 | 123 | ||
124 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | 124 | static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, |
@@ -215,6 +215,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
215 | 215 | ||
216 | icsk->icsk_af_ops = &ipv6_mapped; | 216 | icsk->icsk_af_ops = &ipv6_mapped; |
217 | sk->sk_backlog_rcv = tcp_v4_do_rcv; | 217 | sk->sk_backlog_rcv = tcp_v4_do_rcv; |
218 | #ifdef CONFIG_TCP_MD5SIG | ||
219 | tp->af_specific = &tcp_sock_ipv6_mapped_specific; | ||
220 | #endif | ||
218 | 221 | ||
219 | err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); | 222 | err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); |
220 | 223 | ||
@@ -222,6 +225,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
222 | icsk->icsk_ext_hdr_len = exthdrlen; | 225 | icsk->icsk_ext_hdr_len = exthdrlen; |
223 | icsk->icsk_af_ops = &ipv6_specific; | 226 | icsk->icsk_af_ops = &ipv6_specific; |
224 | sk->sk_backlog_rcv = tcp_v6_do_rcv; | 227 | sk->sk_backlog_rcv = tcp_v6_do_rcv; |
228 | #ifdef CONFIG_TCP_MD5SIG | ||
229 | tp->af_specific = &tcp_sock_ipv6_specific; | ||
230 | #endif | ||
225 | goto failure; | 231 | goto failure; |
226 | } else { | 232 | } else { |
227 | ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), | 233 | ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), |
@@ -310,7 +316,7 @@ failure: | |||
310 | } | 316 | } |
311 | 317 | ||
312 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 318 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
313 | int type, int code, int offset, __u32 info) | 319 | int type, int code, int offset, __be32 info) |
314 | { | 320 | { |
315 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 321 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
316 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 322 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
@@ -509,8 +515,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
509 | 515 | ||
510 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); | 516 | ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); |
511 | err = ip6_xmit(sk, skb, &fl, opt, 0); | 517 | err = ip6_xmit(sk, skb, &fl, opt, 0); |
512 | if (err == NET_XMIT_CN) | 518 | err = net_xmit_eval(err); |
513 | err = 0; | ||
514 | } | 519 | } |
515 | 520 | ||
516 | done: | 521 | done: |
@@ -526,7 +531,396 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) | |||
526 | kfree_skb(inet6_rsk(req)->pktopts); | 531 | kfree_skb(inet6_rsk(req)->pktopts); |
527 | } | 532 | } |
528 | 533 | ||
529 | static struct request_sock_ops tcp6_request_sock_ops = { | 534 | #ifdef CONFIG_TCP_MD5SIG |
535 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | ||
536 | struct in6_addr *addr) | ||
537 | { | ||
538 | struct tcp_sock *tp = tcp_sk(sk); | ||
539 | int i; | ||
540 | |||
541 | BUG_ON(tp == NULL); | ||
542 | |||
543 | if (!tp->md5sig_info || !tp->md5sig_info->entries6) | ||
544 | return NULL; | ||
545 | |||
546 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | ||
547 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | ||
548 | return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; | ||
549 | } | ||
550 | return NULL; | ||
551 | } | ||
552 | |||
553 | static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, | ||
554 | struct sock *addr_sk) | ||
555 | { | ||
556 | return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr); | ||
557 | } | ||
558 | |||
559 | static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | ||
560 | struct request_sock *req) | ||
561 | { | ||
562 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); | ||
563 | } | ||
564 | |||
565 | static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | ||
566 | char *newkey, u8 newkeylen) | ||
567 | { | ||
568 | /* Add key to the list */ | ||
569 | struct tcp6_md5sig_key *key; | ||
570 | struct tcp_sock *tp = tcp_sk(sk); | ||
571 | struct tcp6_md5sig_key *keys; | ||
572 | |||
573 | key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); | ||
574 | if (key) { | ||
575 | /* modify existing entry - just update that one */ | ||
576 | kfree(key->key); | ||
577 | key->key = newkey; | ||
578 | key->keylen = newkeylen; | ||
579 | } else { | ||
580 | /* reallocate new list if current one is full. */ | ||
581 | if (!tp->md5sig_info) { | ||
582 | tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); | ||
583 | if (!tp->md5sig_info) { | ||
584 | kfree(newkey); | ||
585 | return -ENOMEM; | ||
586 | } | ||
587 | } | ||
588 | tcp_alloc_md5sig_pool(); | ||
589 | if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) { | ||
590 | keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) * | ||
591 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); | ||
592 | |||
593 | if (!keys) { | ||
594 | tcp_free_md5sig_pool(); | ||
595 | kfree(newkey); | ||
596 | return -ENOMEM; | ||
597 | } | ||
598 | |||
599 | if (tp->md5sig_info->entries6) | ||
600 | memmove(keys, tp->md5sig_info->keys6, | ||
601 | (sizeof (tp->md5sig_info->keys6[0]) * | ||
602 | tp->md5sig_info->entries6)); | ||
603 | |||
604 | kfree(tp->md5sig_info->keys6); | ||
605 | tp->md5sig_info->keys6 = keys; | ||
606 | tp->md5sig_info->alloced6++; | ||
607 | } | ||
608 | |||
609 | ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, | ||
610 | peer); | ||
611 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; | ||
612 | tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; | ||
613 | |||
614 | tp->md5sig_info->entries6++; | ||
615 | } | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, | ||
620 | u8 *newkey, __u8 newkeylen) | ||
621 | { | ||
622 | return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr, | ||
623 | newkey, newkeylen); | ||
624 | } | ||
625 | |||
626 | static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | ||
627 | { | ||
628 | struct tcp_sock *tp = tcp_sk(sk); | ||
629 | int i; | ||
630 | |||
631 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | ||
632 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | ||
633 | /* Free the key */ | ||
634 | kfree(tp->md5sig_info->keys6[i].key); | ||
635 | tp->md5sig_info->entries6--; | ||
636 | |||
637 | if (tp->md5sig_info->entries6 == 0) { | ||
638 | kfree(tp->md5sig_info->keys6); | ||
639 | tp->md5sig_info->keys6 = NULL; | ||
640 | |||
641 | tcp_free_md5sig_pool(); | ||
642 | |||
643 | return 0; | ||
644 | } else { | ||
645 | /* shrink the database */ | ||
646 | if (tp->md5sig_info->entries6 != i) | ||
647 | memmove(&tp->md5sig_info->keys6[i], | ||
648 | &tp->md5sig_info->keys6[i+1], | ||
649 | (tp->md5sig_info->entries6 - i) | ||
650 | * sizeof (tp->md5sig_info->keys6[0])); | ||
651 | } | ||
652 | } | ||
653 | } | ||
654 | return -ENOENT; | ||
655 | } | ||
656 | |||
657 | static void tcp_v6_clear_md5_list (struct sock *sk) | ||
658 | { | ||
659 | struct tcp_sock *tp = tcp_sk(sk); | ||
660 | int i; | ||
661 | |||
662 | if (tp->md5sig_info->entries6) { | ||
663 | for (i = 0; i < tp->md5sig_info->entries6; i++) | ||
664 | kfree(tp->md5sig_info->keys6[i].key); | ||
665 | tp->md5sig_info->entries6 = 0; | ||
666 | tcp_free_md5sig_pool(); | ||
667 | } | ||
668 | |||
669 | kfree(tp->md5sig_info->keys6); | ||
670 | tp->md5sig_info->keys6 = NULL; | ||
671 | tp->md5sig_info->alloced6 = 0; | ||
672 | |||
673 | if (tp->md5sig_info->entries4) { | ||
674 | for (i = 0; i < tp->md5sig_info->entries4; i++) | ||
675 | kfree(tp->md5sig_info->keys4[i].key); | ||
676 | tp->md5sig_info->entries4 = 0; | ||
677 | tcp_free_md5sig_pool(); | ||
678 | } | ||
679 | |||
680 | kfree(tp->md5sig_info->keys4); | ||
681 | tp->md5sig_info->keys4 = NULL; | ||
682 | tp->md5sig_info->alloced4 = 0; | ||
683 | } | ||
684 | |||
685 | static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | ||
686 | int optlen) | ||
687 | { | ||
688 | struct tcp_md5sig cmd; | ||
689 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; | ||
690 | u8 *newkey; | ||
691 | |||
692 | if (optlen < sizeof(cmd)) | ||
693 | return -EINVAL; | ||
694 | |||
695 | if (copy_from_user(&cmd, optval, sizeof(cmd))) | ||
696 | return -EFAULT; | ||
697 | |||
698 | if (sin6->sin6_family != AF_INET6) | ||
699 | return -EINVAL; | ||
700 | |||
701 | if (!cmd.tcpm_keylen) { | ||
702 | if (!tcp_sk(sk)->md5sig_info) | ||
703 | return -ENOENT; | ||
704 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) | ||
705 | return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]); | ||
706 | return tcp_v6_md5_do_del(sk, &sin6->sin6_addr); | ||
707 | } | ||
708 | |||
709 | if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) | ||
710 | return -EINVAL; | ||
711 | |||
712 | if (!tcp_sk(sk)->md5sig_info) { | ||
713 | struct tcp_sock *tp = tcp_sk(sk); | ||
714 | struct tcp_md5sig_info *p; | ||
715 | |||
716 | p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); | ||
717 | if (!p) | ||
718 | return -ENOMEM; | ||
719 | |||
720 | tp->md5sig_info = p; | ||
721 | } | ||
722 | |||
723 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); | ||
724 | if (!newkey) | ||
725 | return -ENOMEM; | ||
726 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { | ||
727 | return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], | ||
728 | newkey, cmd.tcpm_keylen); | ||
729 | } | ||
730 | return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); | ||
731 | } | ||
732 | |||
733 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
734 | struct in6_addr *saddr, | ||
735 | struct in6_addr *daddr, | ||
736 | struct tcphdr *th, int protocol, | ||
737 | int tcplen) | ||
738 | { | ||
739 | struct scatterlist sg[4]; | ||
740 | __u16 data_len; | ||
741 | int block = 0; | ||
742 | __sum16 cksum; | ||
743 | struct tcp_md5sig_pool *hp; | ||
744 | struct tcp6_pseudohdr *bp; | ||
745 | struct hash_desc *desc; | ||
746 | int err; | ||
747 | unsigned int nbytes = 0; | ||
748 | |||
749 | hp = tcp_get_md5sig_pool(); | ||
750 | if (!hp) { | ||
751 | printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); | ||
752 | goto clear_hash_noput; | ||
753 | } | ||
754 | bp = &hp->md5_blk.ip6; | ||
755 | desc = &hp->md5_desc; | ||
756 | |||
757 | /* 1. TCP pseudo-header (RFC2460) */ | ||
758 | ipv6_addr_copy(&bp->saddr, saddr); | ||
759 | ipv6_addr_copy(&bp->daddr, daddr); | ||
760 | bp->len = htonl(tcplen); | ||
761 | bp->protocol = htonl(protocol); | ||
762 | |||
763 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | ||
764 | nbytes += sizeof(*bp); | ||
765 | |||
766 | /* 2. TCP header, excluding options */ | ||
767 | cksum = th->check; | ||
768 | th->check = 0; | ||
769 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
770 | nbytes += sizeof(*th); | ||
771 | |||
772 | /* 3. TCP segment data (if any) */ | ||
773 | data_len = tcplen - (th->doff << 2); | ||
774 | if (data_len > 0) { | ||
775 | u8 *data = (u8 *)th + (th->doff << 2); | ||
776 | sg_set_buf(&sg[block++], data, data_len); | ||
777 | nbytes += data_len; | ||
778 | } | ||
779 | |||
780 | /* 4. shared key */ | ||
781 | sg_set_buf(&sg[block++], key->key, key->keylen); | ||
782 | nbytes += key->keylen; | ||
783 | |||
784 | /* Now store the hash into the packet */ | ||
785 | err = crypto_hash_init(desc); | ||
786 | if (err) { | ||
787 | printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); | ||
788 | goto clear_hash; | ||
789 | } | ||
790 | err = crypto_hash_update(desc, sg, nbytes); | ||
791 | if (err) { | ||
792 | printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); | ||
793 | goto clear_hash; | ||
794 | } | ||
795 | err = crypto_hash_final(desc, md5_hash); | ||
796 | if (err) { | ||
797 | printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); | ||
798 | goto clear_hash; | ||
799 | } | ||
800 | |||
801 | /* Reset header, and free up the crypto */ | ||
802 | tcp_put_md5sig_pool(); | ||
803 | th->check = cksum; | ||
804 | out: | ||
805 | return 0; | ||
806 | clear_hash: | ||
807 | tcp_put_md5sig_pool(); | ||
808 | clear_hash_noput: | ||
809 | memset(md5_hash, 0, 16); | ||
810 | goto out; | ||
811 | } | ||
812 | |||
813 | static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | ||
814 | struct sock *sk, | ||
815 | struct dst_entry *dst, | ||
816 | struct request_sock *req, | ||
817 | struct tcphdr *th, int protocol, | ||
818 | int tcplen) | ||
819 | { | ||
820 | struct in6_addr *saddr, *daddr; | ||
821 | |||
822 | if (sk) { | ||
823 | saddr = &inet6_sk(sk)->saddr; | ||
824 | daddr = &inet6_sk(sk)->daddr; | ||
825 | } else { | ||
826 | saddr = &inet6_rsk(req)->loc_addr; | ||
827 | daddr = &inet6_rsk(req)->rmt_addr; | ||
828 | } | ||
829 | return tcp_v6_do_calc_md5_hash(md5_hash, key, | ||
830 | saddr, daddr, | ||
831 | th, protocol, tcplen); | ||
832 | } | ||
833 | |||
834 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | ||
835 | { | ||
836 | __u8 *hash_location = NULL; | ||
837 | struct tcp_md5sig_key *hash_expected; | ||
838 | struct ipv6hdr *ip6h = skb->nh.ipv6h; | ||
839 | struct tcphdr *th = skb->h.th; | ||
840 | int length = (th->doff << 2) - sizeof (*th); | ||
841 | int genhash; | ||
842 | u8 *ptr; | ||
843 | u8 newhash[16]; | ||
844 | |||
845 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); | ||
846 | |||
847 | /* If the TCP option is too short, we can short cut */ | ||
848 | if (length < TCPOLEN_MD5SIG) | ||
849 | return hash_expected ? 1 : 0; | ||
850 | |||
851 | /* parse options */ | ||
852 | ptr = (u8*)(th + 1); | ||
853 | while (length > 0) { | ||
854 | int opcode = *ptr++; | ||
855 | int opsize; | ||
856 | |||
857 | switch(opcode) { | ||
858 | case TCPOPT_EOL: | ||
859 | goto done_opts; | ||
860 | case TCPOPT_NOP: | ||
861 | length--; | ||
862 | continue; | ||
863 | default: | ||
864 | opsize = *ptr++; | ||
865 | if (opsize < 2 || opsize > length) | ||
866 | goto done_opts; | ||
867 | if (opcode == TCPOPT_MD5SIG) { | ||
868 | hash_location = ptr; | ||
869 | goto done_opts; | ||
870 | } | ||
871 | } | ||
872 | ptr += opsize - 2; | ||
873 | length -= opsize; | ||
874 | } | ||
875 | |||
876 | done_opts: | ||
877 | /* do we have a hash as expected? */ | ||
878 | if (!hash_expected) { | ||
879 | if (!hash_location) | ||
880 | return 0; | ||
881 | if (net_ratelimit()) { | ||
882 | printk(KERN_INFO "MD5 Hash NOT expected but found " | ||
883 | "(" NIP6_FMT ", %u)->" | ||
884 | "(" NIP6_FMT ", %u)\n", | ||
885 | NIP6(ip6h->saddr), ntohs(th->source), | ||
886 | NIP6(ip6h->daddr), ntohs(th->dest)); | ||
887 | } | ||
888 | return 1; | ||
889 | } | ||
890 | |||
891 | if (!hash_location) { | ||
892 | if (net_ratelimit()) { | ||
893 | printk(KERN_INFO "MD5 Hash expected but NOT found " | ||
894 | "(" NIP6_FMT ", %u)->" | ||
895 | "(" NIP6_FMT ", %u)\n", | ||
896 | NIP6(ip6h->saddr), ntohs(th->source), | ||
897 | NIP6(ip6h->daddr), ntohs(th->dest)); | ||
898 | } | ||
899 | return 1; | ||
900 | } | ||
901 | |||
902 | /* check the signature */ | ||
903 | genhash = tcp_v6_do_calc_md5_hash(newhash, | ||
904 | hash_expected, | ||
905 | &ip6h->saddr, &ip6h->daddr, | ||
906 | th, sk->sk_protocol, | ||
907 | skb->len); | ||
908 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | ||
909 | if (net_ratelimit()) { | ||
910 | printk(KERN_INFO "MD5 Hash %s for " | ||
911 | "(" NIP6_FMT ", %u)->" | ||
912 | "(" NIP6_FMT ", %u)\n", | ||
913 | genhash ? "failed" : "mismatch", | ||
914 | NIP6(ip6h->saddr), ntohs(th->source), | ||
915 | NIP6(ip6h->daddr), ntohs(th->dest)); | ||
916 | } | ||
917 | return 1; | ||
918 | } | ||
919 | return 0; | ||
920 | } | ||
921 | #endif | ||
922 | |||
923 | static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | ||
530 | .family = AF_INET6, | 924 | .family = AF_INET6, |
531 | .obj_size = sizeof(struct tcp6_request_sock), | 925 | .obj_size = sizeof(struct tcp6_request_sock), |
532 | .rtx_syn_ack = tcp_v6_send_synack, | 926 | .rtx_syn_ack = tcp_v6_send_synack, |
@@ -535,9 +929,16 @@ static struct request_sock_ops tcp6_request_sock_ops = { | |||
535 | .send_reset = tcp_v6_send_reset | 929 | .send_reset = tcp_v6_send_reset |
536 | }; | 930 | }; |
537 | 931 | ||
932 | #ifdef CONFIG_TCP_MD5SIG | ||
933 | static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | ||
934 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | ||
935 | }; | ||
936 | #endif | ||
937 | |||
538 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | 938 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { |
539 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | 939 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), |
540 | .twsk_unique = tcp_twsk_unique, | 940 | .twsk_unique = tcp_twsk_unique, |
941 | .twsk_destructor= tcp_twsk_destructor, | ||
541 | }; | 942 | }; |
542 | 943 | ||
543 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) | 944 | static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) |
@@ -547,7 +948,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) | |||
547 | 948 | ||
548 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 949 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
549 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); | 950 | th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); |
550 | skb->csum = offsetof(struct tcphdr, check); | 951 | skb->csum_offset = offsetof(struct tcphdr, check); |
551 | } else { | 952 | } else { |
552 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, | 953 | th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, |
553 | csum_partial((char *)th, th->doff<<2, | 954 | csum_partial((char *)th, th->doff<<2, |
@@ -569,16 +970,20 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
569 | th->check = 0; | 970 | th->check = 0; |
570 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, | 971 | th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, |
571 | IPPROTO_TCP, 0); | 972 | IPPROTO_TCP, 0); |
572 | skb->csum = offsetof(struct tcphdr, check); | 973 | skb->csum_offset = offsetof(struct tcphdr, check); |
573 | skb->ip_summed = CHECKSUM_PARTIAL; | 974 | skb->ip_summed = CHECKSUM_PARTIAL; |
574 | return 0; | 975 | return 0; |
575 | } | 976 | } |
576 | 977 | ||
577 | static void tcp_v6_send_reset(struct sk_buff *skb) | 978 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) |
578 | { | 979 | { |
579 | struct tcphdr *th = skb->h.th, *t1; | 980 | struct tcphdr *th = skb->h.th, *t1; |
580 | struct sk_buff *buff; | 981 | struct sk_buff *buff; |
581 | struct flowi fl; | 982 | struct flowi fl; |
983 | int tot_len = sizeof(*th); | ||
984 | #ifdef CONFIG_TCP_MD5SIG | ||
985 | struct tcp_md5sig_key *key; | ||
986 | #endif | ||
582 | 987 | ||
583 | if (th->rst) | 988 | if (th->rst) |
584 | return; | 989 | return; |
@@ -586,25 +991,35 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
586 | if (!ipv6_unicast_destination(skb)) | 991 | if (!ipv6_unicast_destination(skb)) |
587 | return; | 992 | return; |
588 | 993 | ||
994 | #ifdef CONFIG_TCP_MD5SIG | ||
995 | if (sk) | ||
996 | key = tcp_v6_md5_do_lookup(sk, &skb->nh.ipv6h->daddr); | ||
997 | else | ||
998 | key = NULL; | ||
999 | |||
1000 | if (key) | ||
1001 | tot_len += TCPOLEN_MD5SIG_ALIGNED; | ||
1002 | #endif | ||
1003 | |||
589 | /* | 1004 | /* |
590 | * We need to grab some memory, and put together an RST, | 1005 | * We need to grab some memory, and put together an RST, |
591 | * and then put it into the queue to be sent. | 1006 | * and then put it into the queue to be sent. |
592 | */ | 1007 | */ |
593 | 1008 | ||
594 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr), | 1009 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, |
595 | GFP_ATOMIC); | 1010 | GFP_ATOMIC); |
596 | if (buff == NULL) | 1011 | if (buff == NULL) |
597 | return; | 1012 | return; |
598 | 1013 | ||
599 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr)); | 1014 | skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); |
600 | 1015 | ||
601 | t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr)); | 1016 | t1 = (struct tcphdr *) skb_push(buff, tot_len); |
602 | 1017 | ||
603 | /* Swap the send and the receive. */ | 1018 | /* Swap the send and the receive. */ |
604 | memset(t1, 0, sizeof(*t1)); | 1019 | memset(t1, 0, sizeof(*t1)); |
605 | t1->dest = th->source; | 1020 | t1->dest = th->source; |
606 | t1->source = th->dest; | 1021 | t1->source = th->dest; |
607 | t1->doff = sizeof(*t1)/4; | 1022 | t1->doff = tot_len / 4; |
608 | t1->rst = 1; | 1023 | t1->rst = 1; |
609 | 1024 | ||
610 | if(th->ack) { | 1025 | if(th->ack) { |
@@ -615,6 +1030,22 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
615 | + skb->len - (th->doff<<2)); | 1030 | + skb->len - (th->doff<<2)); |
616 | } | 1031 | } |
617 | 1032 | ||
1033 | #ifdef CONFIG_TCP_MD5SIG | ||
1034 | if (key) { | ||
1035 | __be32 *opt = (__be32*)(t1 + 1); | ||
1036 | opt[0] = htonl((TCPOPT_NOP << 24) | | ||
1037 | (TCPOPT_NOP << 16) | | ||
1038 | (TCPOPT_MD5SIG << 8) | | ||
1039 | TCPOLEN_MD5SIG); | ||
1040 | tcp_v6_do_calc_md5_hash((__u8*)&opt[1], | ||
1041 | key, | ||
1042 | &skb->nh.ipv6h->daddr, | ||
1043 | &skb->nh.ipv6h->saddr, | ||
1044 | t1, IPPROTO_TCP, | ||
1045 | tot_len); | ||
1046 | } | ||
1047 | #endif | ||
1048 | |||
618 | buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); | 1049 | buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); |
619 | 1050 | ||
620 | memset(&fl, 0, sizeof(fl)); | 1051 | memset(&fl, 0, sizeof(fl)); |
@@ -645,15 +1076,37 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
645 | kfree_skb(buff); | 1076 | kfree_skb(buff); |
646 | } | 1077 | } |
647 | 1078 | ||
648 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1079 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, |
1080 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | ||
649 | { | 1081 | { |
650 | struct tcphdr *th = skb->h.th, *t1; | 1082 | struct tcphdr *th = skb->h.th, *t1; |
651 | struct sk_buff *buff; | 1083 | struct sk_buff *buff; |
652 | struct flowi fl; | 1084 | struct flowi fl; |
653 | int tot_len = sizeof(struct tcphdr); | 1085 | int tot_len = sizeof(struct tcphdr); |
1086 | __be32 *topt; | ||
1087 | #ifdef CONFIG_TCP_MD5SIG | ||
1088 | struct tcp_md5sig_key *key; | ||
1089 | struct tcp_md5sig_key tw_key; | ||
1090 | #endif | ||
1091 | |||
1092 | #ifdef CONFIG_TCP_MD5SIG | ||
1093 | if (!tw && skb->sk) { | ||
1094 | key = tcp_v6_md5_do_lookup(skb->sk, &skb->nh.ipv6h->daddr); | ||
1095 | } else if (tw && tw->tw_md5_keylen) { | ||
1096 | tw_key.key = tw->tw_md5_key; | ||
1097 | tw_key.keylen = tw->tw_md5_keylen; | ||
1098 | key = &tw_key; | ||
1099 | } else { | ||
1100 | key = NULL; | ||
1101 | } | ||
1102 | #endif | ||
654 | 1103 | ||
655 | if (ts) | 1104 | if (ts) |
656 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 1105 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
1106 | #ifdef CONFIG_TCP_MD5SIG | ||
1107 | if (key) | ||
1108 | tot_len += TCPOLEN_MD5SIG_ALIGNED; | ||
1109 | #endif | ||
657 | 1110 | ||
658 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, | 1111 | buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, |
659 | GFP_ATOMIC); | 1112 | GFP_ATOMIC); |
@@ -673,15 +1126,29 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
673 | t1->ack_seq = htonl(ack); | 1126 | t1->ack_seq = htonl(ack); |
674 | t1->ack = 1; | 1127 | t1->ack = 1; |
675 | t1->window = htons(win); | 1128 | t1->window = htons(win); |
1129 | |||
1130 | topt = (__be32 *)(t1 + 1); | ||
676 | 1131 | ||
677 | if (ts) { | 1132 | if (ts) { |
678 | u32 *ptr = (u32*)(t1 + 1); | 1133 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
679 | *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 1134 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); |
680 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); | 1135 | *topt++ = htonl(tcp_time_stamp); |
681 | *ptr++ = htonl(tcp_time_stamp); | 1136 | *topt = htonl(ts); |
682 | *ptr = htonl(ts); | ||
683 | } | 1137 | } |
684 | 1138 | ||
1139 | #ifdef CONFIG_TCP_MD5SIG | ||
1140 | if (key) { | ||
1141 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | ||
1142 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); | ||
1143 | tcp_v6_do_calc_md5_hash((__u8 *)topt, | ||
1144 | key, | ||
1145 | &skb->nh.ipv6h->daddr, | ||
1146 | &skb->nh.ipv6h->saddr, | ||
1147 | t1, IPPROTO_TCP, | ||
1148 | tot_len); | ||
1149 | } | ||
1150 | #endif | ||
1151 | |||
685 | buff->csum = csum_partial((char *)t1, tot_len, 0); | 1152 | buff->csum = csum_partial((char *)t1, tot_len, 0); |
686 | 1153 | ||
687 | memset(&fl, 0, sizeof(fl)); | 1154 | memset(&fl, 0, sizeof(fl)); |
@@ -712,9 +1179,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
712 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | 1179 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) |
713 | { | 1180 | { |
714 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1181 | struct inet_timewait_sock *tw = inet_twsk(sk); |
715 | const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 1182 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
716 | 1183 | ||
717 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1184 | tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
718 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1185 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
719 | tcptw->tw_ts_recent); | 1186 | tcptw->tw_ts_recent); |
720 | 1187 | ||
@@ -723,7 +1190,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
723 | 1190 | ||
724 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1191 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
725 | { | 1192 | { |
726 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); | 1193 | tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); |
727 | } | 1194 | } |
728 | 1195 | ||
729 | 1196 | ||
@@ -794,6 +1261,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
794 | if (req == NULL) | 1261 | if (req == NULL) |
795 | goto drop; | 1262 | goto drop; |
796 | 1263 | ||
1264 | #ifdef CONFIG_TCP_MD5SIG | ||
1265 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; | ||
1266 | #endif | ||
1267 | |||
797 | tcp_clear_options(&tmp_opt); | 1268 | tcp_clear_options(&tmp_opt); |
798 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | 1269 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); |
799 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 1270 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
@@ -822,7 +1293,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
822 | treq->iif = inet6_iif(skb); | 1293 | treq->iif = inet6_iif(skb); |
823 | 1294 | ||
824 | if (isn == 0) | 1295 | if (isn == 0) |
825 | isn = tcp_v6_init_sequence(sk,skb); | 1296 | isn = tcp_v6_init_sequence(skb); |
826 | 1297 | ||
827 | tcp_rsk(req)->snt_isn = isn; | 1298 | tcp_rsk(req)->snt_isn = isn; |
828 | 1299 | ||
@@ -852,6 +1323,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
852 | struct tcp_sock *newtp; | 1323 | struct tcp_sock *newtp; |
853 | struct sock *newsk; | 1324 | struct sock *newsk; |
854 | struct ipv6_txoptions *opt; | 1325 | struct ipv6_txoptions *opt; |
1326 | #ifdef CONFIG_TCP_MD5SIG | ||
1327 | struct tcp_md5sig_key *key; | ||
1328 | #endif | ||
855 | 1329 | ||
856 | if (skb->protocol == htons(ETH_P_IP)) { | 1330 | if (skb->protocol == htons(ETH_P_IP)) { |
857 | /* | 1331 | /* |
@@ -882,6 +1356,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
882 | 1356 | ||
883 | inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; | 1357 | inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; |
884 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; | 1358 | newsk->sk_backlog_rcv = tcp_v4_do_rcv; |
1359 | #ifdef CONFIG_TCP_MD5SIG | ||
1360 | newtp->af_specific = &tcp_sock_ipv6_mapped_specific; | ||
1361 | #endif | ||
1362 | |||
885 | newnp->pktoptions = NULL; | 1363 | newnp->pktoptions = NULL; |
886 | newnp->opt = NULL; | 1364 | newnp->opt = NULL; |
887 | newnp->mcast_oif = inet6_iif(skb); | 1365 | newnp->mcast_oif = inet6_iif(skb); |
@@ -1016,6 +1494,21 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1016 | 1494 | ||
1017 | newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; | 1495 | newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; |
1018 | 1496 | ||
1497 | #ifdef CONFIG_TCP_MD5SIG | ||
1498 | /* Copy over the MD5 key from the original socket */ | ||
1499 | if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) { | ||
1500 | /* We're using one, so create a matching key | ||
1501 | * on the newsk structure. If we fail to get | ||
1502 | * memory, then we end up not copying the key | ||
1503 | * across. Shucks. | ||
1504 | */ | ||
1505 | char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); | ||
1506 | if (newkey != NULL) | ||
1507 | tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, | ||
1508 | newkey, key->keylen); | ||
1509 | } | ||
1510 | #endif | ||
1511 | |||
1019 | __inet6_hash(&tcp_hashinfo, newsk); | 1512 | __inet6_hash(&tcp_hashinfo, newsk); |
1020 | inet_inherit_port(&tcp_hashinfo, sk, newsk); | 1513 | inet_inherit_port(&tcp_hashinfo, sk, newsk); |
1021 | 1514 | ||
@@ -1031,7 +1524,7 @@ out: | |||
1031 | return NULL; | 1524 | return NULL; |
1032 | } | 1525 | } |
1033 | 1526 | ||
1034 | static int tcp_v6_checksum_init(struct sk_buff *skb) | 1527 | static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) |
1035 | { | 1528 | { |
1036 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | 1529 | if (skb->ip_summed == CHECKSUM_COMPLETE) { |
1037 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1530 | if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, |
@@ -1041,8 +1534,8 @@ static int tcp_v6_checksum_init(struct sk_buff *skb) | |||
1041 | } | 1534 | } |
1042 | } | 1535 | } |
1043 | 1536 | ||
1044 | skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, | 1537 | skb->csum = ~csum_unfold(tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, |
1045 | &skb->nh.ipv6h->daddr, 0); | 1538 | &skb->nh.ipv6h->daddr, 0)); |
1046 | 1539 | ||
1047 | if (skb->len <= 76) { | 1540 | if (skb->len <= 76) { |
1048 | return __skb_checksum_complete(skb); | 1541 | return __skb_checksum_complete(skb); |
@@ -1075,6 +1568,11 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1075 | if (skb->protocol == htons(ETH_P_IP)) | 1568 | if (skb->protocol == htons(ETH_P_IP)) |
1076 | return tcp_v4_do_rcv(sk, skb); | 1569 | return tcp_v4_do_rcv(sk, skb); |
1077 | 1570 | ||
1571 | #ifdef CONFIG_TCP_MD5SIG | ||
1572 | if (tcp_v6_inbound_md5_hash (sk, skb)) | ||
1573 | goto discard; | ||
1574 | #endif | ||
1575 | |||
1078 | if (sk_filter(sk, skb)) | 1576 | if (sk_filter(sk, skb)) |
1079 | goto discard; | 1577 | goto discard; |
1080 | 1578 | ||
@@ -1140,7 +1638,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1140 | return 0; | 1638 | return 0; |
1141 | 1639 | ||
1142 | reset: | 1640 | reset: |
1143 | tcp_v6_send_reset(skb); | 1641 | tcp_v6_send_reset(sk, skb); |
1144 | discard: | 1642 | discard: |
1145 | if (opt_skb) | 1643 | if (opt_skb) |
1146 | __kfree_skb(opt_skb); | 1644 | __kfree_skb(opt_skb); |
@@ -1265,7 +1763,7 @@ no_tcp_socket: | |||
1265 | bad_packet: | 1763 | bad_packet: |
1266 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1764 | TCP_INC_STATS_BH(TCP_MIB_INERRS); |
1267 | } else { | 1765 | } else { |
1268 | tcp_v6_send_reset(skb); | 1766 | tcp_v6_send_reset(NULL, skb); |
1269 | } | 1767 | } |
1270 | 1768 | ||
1271 | discard_it: | 1769 | discard_it: |
@@ -1344,6 +1842,15 @@ static struct inet_connection_sock_af_ops ipv6_specific = { | |||
1344 | #endif | 1842 | #endif |
1345 | }; | 1843 | }; |
1346 | 1844 | ||
1845 | #ifdef CONFIG_TCP_MD5SIG | ||
1846 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { | ||
1847 | .md5_lookup = tcp_v6_md5_lookup, | ||
1848 | .calc_md5_hash = tcp_v6_calc_md5_hash, | ||
1849 | .md5_add = tcp_v6_md5_add_func, | ||
1850 | .md5_parse = tcp_v6_parse_md5_keys, | ||
1851 | }; | ||
1852 | #endif | ||
1853 | |||
1347 | /* | 1854 | /* |
1348 | * TCP over IPv4 via INET6 API | 1855 | * TCP over IPv4 via INET6 API |
1349 | */ | 1856 | */ |
@@ -1366,6 +1873,15 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1366 | #endif | 1873 | #endif |
1367 | }; | 1874 | }; |
1368 | 1875 | ||
1876 | #ifdef CONFIG_TCP_MD5SIG | ||
1877 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { | ||
1878 | .md5_lookup = tcp_v4_md5_lookup, | ||
1879 | .calc_md5_hash = tcp_v4_calc_md5_hash, | ||
1880 | .md5_add = tcp_v6_md5_add_func, | ||
1881 | .md5_parse = tcp_v6_parse_md5_keys, | ||
1882 | }; | ||
1883 | #endif | ||
1884 | |||
1369 | /* NOTE: A lot of things set to zero explicitly by call to | 1885 | /* NOTE: A lot of things set to zero explicitly by call to |
1370 | * sk_alloc() so need not be done here. | 1886 | * sk_alloc() so need not be done here. |
1371 | */ | 1887 | */ |
@@ -1405,6 +1921,10 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1405 | sk->sk_write_space = sk_stream_write_space; | 1921 | sk->sk_write_space = sk_stream_write_space; |
1406 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); | 1922 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); |
1407 | 1923 | ||
1924 | #ifdef CONFIG_TCP_MD5SIG | ||
1925 | tp->af_specific = &tcp_sock_ipv6_specific; | ||
1926 | #endif | ||
1927 | |||
1408 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; | 1928 | sk->sk_sndbuf = sysctl_tcp_wmem[1]; |
1409 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; | 1929 | sk->sk_rcvbuf = sysctl_tcp_rmem[1]; |
1410 | 1930 | ||
@@ -1415,6 +1935,11 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1415 | 1935 | ||
1416 | static int tcp_v6_destroy_sock(struct sock *sk) | 1936 | static int tcp_v6_destroy_sock(struct sock *sk) |
1417 | { | 1937 | { |
1938 | #ifdef CONFIG_TCP_MD5SIG | ||
1939 | /* Clean up the MD5 key list */ | ||
1940 | if (tcp_sk(sk)->md5sig_info) | ||
1941 | tcp_v6_clear_md5_list(sk); | ||
1942 | #endif | ||
1418 | tcp_v4_destroy_sock(sk); | 1943 | tcp_v4_destroy_sock(sk); |
1419 | return inet6_destroy_sock(sk); | 1944 | return inet6_destroy_sock(sk); |
1420 | } | 1945 | } |
diff --git a/net/ipv6/tunnel6.c b/net/ipv6/tunnel6.c index 0ef9a35798d1..918d07dd1219 100644 --- a/net/ipv6/tunnel6.c +++ b/net/ipv6/tunnel6.c | |||
@@ -104,7 +104,7 @@ drop: | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 106 | static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
107 | int type, int code, int offset, __u32 info) | 107 | int type, int code, int offset, __be32 info) |
108 | { | 108 | { |
109 | struct xfrm6_tunnel *handler; | 109 | struct xfrm6_tunnel *handler; |
110 | 110 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index c83f23e51c46..f52a5c3cc0a3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -38,26 +38,18 @@ | |||
38 | #include <linux/skbuff.h> | 38 | #include <linux/skbuff.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | 40 | ||
41 | #include <net/sock.h> | ||
42 | #include <net/snmp.h> | ||
43 | |||
44 | #include <net/ipv6.h> | ||
45 | #include <net/ndisc.h> | 41 | #include <net/ndisc.h> |
46 | #include <net/protocol.h> | 42 | #include <net/protocol.h> |
47 | #include <net/transp_v6.h> | 43 | #include <net/transp_v6.h> |
48 | #include <net/ip6_route.h> | 44 | #include <net/ip6_route.h> |
49 | #include <net/addrconf.h> | ||
50 | #include <net/ip.h> | ||
51 | #include <net/udp.h> | ||
52 | #include <net/raw.h> | 45 | #include <net/raw.h> |
53 | #include <net/inet_common.h> | ||
54 | #include <net/tcp_states.h> | 46 | #include <net/tcp_states.h> |
55 | |||
56 | #include <net/ip6_checksum.h> | 47 | #include <net/ip6_checksum.h> |
57 | #include <net/xfrm.h> | 48 | #include <net/xfrm.h> |
58 | 49 | ||
59 | #include <linux/proc_fs.h> | 50 | #include <linux/proc_fs.h> |
60 | #include <linux/seq_file.h> | 51 | #include <linux/seq_file.h> |
52 | #include "udp_impl.h" | ||
61 | 53 | ||
62 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; | 54 | DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; |
63 | 55 | ||
@@ -66,23 +58,9 @@ static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
66 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); | 58 | return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); |
67 | } | 59 | } |
68 | 60 | ||
69 | static void udp_v6_hash(struct sock *sk) | 61 | static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport, |
70 | { | 62 | struct in6_addr *daddr, __be16 dport, |
71 | BUG(); | 63 | int dif, struct hlist_head udptable[]) |
72 | } | ||
73 | |||
74 | static void udp_v6_unhash(struct sock *sk) | ||
75 | { | ||
76 | write_lock_bh(&udp_hash_lock); | ||
77 | if (sk_del_node_init(sk)) { | ||
78 | inet_sk(sk)->num = 0; | ||
79 | sock_prot_dec_use(sk->sk_prot); | ||
80 | } | ||
81 | write_unlock_bh(&udp_hash_lock); | ||
82 | } | ||
83 | |||
84 | static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, | ||
85 | struct in6_addr *daddr, u16 dport, int dif) | ||
86 | { | 64 | { |
87 | struct sock *sk, *result = NULL; | 65 | struct sock *sk, *result = NULL; |
88 | struct hlist_node *node; | 66 | struct hlist_node *node; |
@@ -90,7 +68,7 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, | |||
90 | int badness = -1; | 68 | int badness = -1; |
91 | 69 | ||
92 | read_lock(&udp_hash_lock); | 70 | read_lock(&udp_hash_lock); |
93 | sk_for_each(sk, node, &udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]) { | 71 | sk_for_each(sk, node, &udptable[hnum & (UDP_HTABLE_SIZE - 1)]) { |
94 | struct inet_sock *inet = inet_sk(sk); | 72 | struct inet_sock *inet = inet_sk(sk); |
95 | 73 | ||
96 | if (inet->num == hnum && sk->sk_family == PF_INET6) { | 74 | if (inet->num == hnum && sk->sk_family == PF_INET6) { |
@@ -132,20 +110,11 @@ static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport, | |||
132 | } | 110 | } |
133 | 111 | ||
134 | /* | 112 | /* |
135 | * | ||
136 | */ | ||
137 | |||
138 | static void udpv6_close(struct sock *sk, long timeout) | ||
139 | { | ||
140 | sk_common_release(sk); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * This should be easy, if there is something there we | 113 | * This should be easy, if there is something there we |
145 | * return it, otherwise we block. | 114 | * return it, otherwise we block. |
146 | */ | 115 | */ |
147 | 116 | ||
148 | static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | 117 | int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, |
149 | struct msghdr *msg, size_t len, | 118 | struct msghdr *msg, size_t len, |
150 | int noblock, int flags, int *addr_len) | 119 | int noblock, int flags, int *addr_len) |
151 | { | 120 | { |
@@ -153,7 +122,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
153 | struct inet_sock *inet = inet_sk(sk); | 122 | struct inet_sock *inet = inet_sk(sk); |
154 | struct sk_buff *skb; | 123 | struct sk_buff *skb; |
155 | size_t copied; | 124 | size_t copied; |
156 | int err; | 125 | int err, copy_only, is_udplite = IS_UDPLITE(sk); |
157 | 126 | ||
158 | if (addr_len) | 127 | if (addr_len) |
159 | *addr_len=sizeof(struct sockaddr_in6); | 128 | *addr_len=sizeof(struct sockaddr_in6); |
@@ -172,15 +141,21 @@ try_again: | |||
172 | msg->msg_flags |= MSG_TRUNC; | 141 | msg->msg_flags |= MSG_TRUNC; |
173 | } | 142 | } |
174 | 143 | ||
175 | if (skb->ip_summed==CHECKSUM_UNNECESSARY) { | 144 | /* |
176 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, | 145 | * Decide whether to checksum and/or copy data. |
177 | copied); | 146 | */ |
178 | } else if (msg->msg_flags&MSG_TRUNC) { | 147 | copy_only = (skb->ip_summed==CHECKSUM_UNNECESSARY); |
179 | if (__skb_checksum_complete(skb)) | 148 | |
149 | if (is_udplite || (!copy_only && msg->msg_flags&MSG_TRUNC)) { | ||
150 | if (__udp_lib_checksum_complete(skb)) | ||
180 | goto csum_copy_err; | 151 | goto csum_copy_err; |
181 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov, | 152 | copy_only = 1; |
182 | copied); | 153 | } |
183 | } else { | 154 | |
155 | if (copy_only) | ||
156 | err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), | ||
157 | msg->msg_iov, copied ); | ||
158 | else { | ||
184 | err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); | 159 | err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); |
185 | if (err == -EINVAL) | 160 | if (err == -EINVAL) |
186 | goto csum_copy_err; | 161 | goto csum_copy_err; |
@@ -231,14 +206,15 @@ csum_copy_err: | |||
231 | skb_kill_datagram(sk, skb, flags); | 206 | skb_kill_datagram(sk, skb, flags); |
232 | 207 | ||
233 | if (flags & MSG_DONTWAIT) { | 208 | if (flags & MSG_DONTWAIT) { |
234 | UDP6_INC_STATS_USER(UDP_MIB_INERRORS); | 209 | UDP6_INC_STATS_USER(UDP_MIB_INERRORS, is_udplite); |
235 | return -EAGAIN; | 210 | return -EAGAIN; |
236 | } | 211 | } |
237 | goto try_again; | 212 | goto try_again; |
238 | } | 213 | } |
239 | 214 | ||
240 | static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 215 | void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
241 | int type, int code, int offset, __u32 info) | 216 | int type, int code, int offset, __be32 info, |
217 | struct hlist_head udptable[] ) | ||
242 | { | 218 | { |
243 | struct ipv6_pinfo *np; | 219 | struct ipv6_pinfo *np; |
244 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 220 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; |
@@ -248,8 +224,8 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
248 | struct sock *sk; | 224 | struct sock *sk; |
249 | int err; | 225 | int err; |
250 | 226 | ||
251 | sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, inet6_iif(skb)); | 227 | sk = __udp6_lib_lookup(daddr, uh->dest, |
252 | 228 | saddr, uh->source, inet6_iif(skb), udptable); | |
253 | if (sk == NULL) | 229 | if (sk == NULL) |
254 | return; | 230 | return; |
255 | 231 | ||
@@ -270,36 +246,60 @@ out: | |||
270 | sock_put(sk); | 246 | sock_put(sk); |
271 | } | 247 | } |
272 | 248 | ||
273 | static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | 249 | static __inline__ void udpv6_err(struct sk_buff *skb, |
250 | struct inet6_skb_parm *opt, int type, | ||
251 | int code, int offset, __be32 info ) | ||
252 | { | ||
253 | return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash); | ||
254 | } | ||
255 | |||
256 | int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | ||
274 | { | 257 | { |
258 | struct udp_sock *up = udp_sk(sk); | ||
275 | int rc; | 259 | int rc; |
276 | 260 | ||
277 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { | 261 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
278 | kfree_skb(skb); | 262 | goto drop; |
279 | return -1; | ||
280 | } | ||
281 | 263 | ||
282 | if (skb_checksum_complete(skb)) { | 264 | /* |
283 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS); | 265 | * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). |
284 | kfree_skb(skb); | 266 | */ |
285 | return 0; | 267 | if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { |
268 | |||
269 | if (up->pcrlen == 0) { /* full coverage was set */ | ||
270 | LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: partial coverage" | ||
271 | " %d while full coverage %d requested\n", | ||
272 | UDP_SKB_CB(skb)->cscov, skb->len); | ||
273 | goto drop; | ||
274 | } | ||
275 | if (UDP_SKB_CB(skb)->cscov < up->pcrlen) { | ||
276 | LIMIT_NETDEBUG(KERN_WARNING "UDPLITE6: coverage %d " | ||
277 | "too small, need min %d\n", | ||
278 | UDP_SKB_CB(skb)->cscov, up->pcrlen); | ||
279 | goto drop; | ||
280 | } | ||
286 | } | 281 | } |
287 | 282 | ||
283 | if (udp_lib_checksum_complete(skb)) | ||
284 | goto drop; | ||
285 | |||
288 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { | 286 | if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { |
289 | /* Note that an ENOMEM error is charged twice */ | 287 | /* Note that an ENOMEM error is charged twice */ |
290 | if (rc == -ENOMEM) | 288 | if (rc == -ENOMEM) |
291 | UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); | 289 | UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS, up->pcflag); |
292 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS); | 290 | goto drop; |
293 | kfree_skb(skb); | ||
294 | return 0; | ||
295 | } | 291 | } |
296 | UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS); | 292 | UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS, up->pcflag); |
297 | return 0; | 293 | return 0; |
294 | drop: | ||
295 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS, up->pcflag); | ||
296 | kfree_skb(skb); | ||
297 | return -1; | ||
298 | } | 298 | } |
299 | 299 | ||
300 | static struct sock *udp_v6_mcast_next(struct sock *sk, | 300 | static struct sock *udp_v6_mcast_next(struct sock *sk, |
301 | u16 loc_port, struct in6_addr *loc_addr, | 301 | __be16 loc_port, struct in6_addr *loc_addr, |
302 | u16 rmt_port, struct in6_addr *rmt_addr, | 302 | __be16 rmt_port, struct in6_addr *rmt_addr, |
303 | int dif) | 303 | int dif) |
304 | { | 304 | { |
305 | struct hlist_node *node; | 305 | struct hlist_node *node; |
@@ -338,15 +338,15 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
338 | * Note: called only from the BH handler context, | 338 | * Note: called only from the BH handler context, |
339 | * so we don't need to lock the hashes. | 339 | * so we don't need to lock the hashes. |
340 | */ | 340 | */ |
341 | static void udpv6_mcast_deliver(struct udphdr *uh, | 341 | static int __udp6_lib_mcast_deliver(struct sk_buff *skb, struct in6_addr *saddr, |
342 | struct in6_addr *saddr, struct in6_addr *daddr, | 342 | struct in6_addr *daddr, struct hlist_head udptable[]) |
343 | struct sk_buff *skb) | ||
344 | { | 343 | { |
345 | struct sock *sk, *sk2; | 344 | struct sock *sk, *sk2; |
345 | const struct udphdr *uh = skb->h.uh; | ||
346 | int dif; | 346 | int dif; |
347 | 347 | ||
348 | read_lock(&udp_hash_lock); | 348 | read_lock(&udp_hash_lock); |
349 | sk = sk_head(&udp_hash[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); | 349 | sk = sk_head(&udptable[ntohs(uh->dest) & (UDP_HTABLE_SIZE - 1)]); |
350 | dif = inet6_iif(skb); | 350 | dif = inet6_iif(skb); |
351 | sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); | 351 | sk = udp_v6_mcast_next(sk, uh->dest, daddr, uh->source, saddr, dif); |
352 | if (!sk) { | 352 | if (!sk) { |
@@ -364,9 +364,35 @@ static void udpv6_mcast_deliver(struct udphdr *uh, | |||
364 | udpv6_queue_rcv_skb(sk, skb); | 364 | udpv6_queue_rcv_skb(sk, skb); |
365 | out: | 365 | out: |
366 | read_unlock(&udp_hash_lock); | 366 | read_unlock(&udp_hash_lock); |
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) | ||
371 | |||
372 | { | ||
373 | if (uh->check == 0) { | ||
374 | /* RFC 2460 section 8.1 says that we SHOULD log | ||
375 | this error. Well, it is reasonable. | ||
376 | */ | ||
377 | LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); | ||
378 | return 1; | ||
379 | } | ||
380 | if (skb->ip_summed == CHECKSUM_COMPLETE && | ||
381 | !csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, | ||
382 | skb->len, IPPROTO_UDP, skb->csum )) | ||
383 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
384 | |||
385 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
386 | skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, | ||
387 | &skb->nh.ipv6h->daddr, | ||
388 | skb->len, IPPROTO_UDP, | ||
389 | 0)); | ||
390 | |||
391 | return (UDP_SKB_CB(skb)->partial_cov = 0); | ||
367 | } | 392 | } |
368 | 393 | ||
369 | static int udpv6_rcv(struct sk_buff **pskb) | 394 | int __udp6_lib_rcv(struct sk_buff **pskb, struct hlist_head udptable[], |
395 | int is_udplite) | ||
370 | { | 396 | { |
371 | struct sk_buff *skb = *pskb; | 397 | struct sk_buff *skb = *pskb; |
372 | struct sock *sk; | 398 | struct sock *sk; |
@@ -383,44 +409,39 @@ static int udpv6_rcv(struct sk_buff **pskb) | |||
383 | uh = skb->h.uh; | 409 | uh = skb->h.uh; |
384 | 410 | ||
385 | ulen = ntohs(uh->len); | 411 | ulen = ntohs(uh->len); |
412 | if (ulen > skb->len) | ||
413 | goto short_packet; | ||
386 | 414 | ||
387 | /* Check for jumbo payload */ | 415 | if(! is_udplite ) { /* UDP validates ulen. */ |
388 | if (ulen == 0) | ||
389 | ulen = skb->len; | ||
390 | 416 | ||
391 | if (ulen > skb->len || ulen < sizeof(*uh)) | 417 | /* Check for jumbo payload */ |
392 | goto short_packet; | 418 | if (ulen == 0) |
419 | ulen = skb->len; | ||
393 | 420 | ||
394 | if (uh->check == 0) { | 421 | if (ulen < sizeof(*uh)) |
395 | /* RFC 2460 section 8.1 says that we SHOULD log | 422 | goto short_packet; |
396 | this error. Well, it is reasonable. | ||
397 | */ | ||
398 | LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); | ||
399 | goto discard; | ||
400 | } | ||
401 | 423 | ||
402 | if (ulen < skb->len) { | 424 | if (ulen < skb->len) { |
403 | if (pskb_trim_rcsum(skb, ulen)) | 425 | if (pskb_trim_rcsum(skb, ulen)) |
404 | goto discard; | 426 | goto short_packet; |
405 | saddr = &skb->nh.ipv6h->saddr; | 427 | saddr = &skb->nh.ipv6h->saddr; |
406 | daddr = &skb->nh.ipv6h->daddr; | 428 | daddr = &skb->nh.ipv6h->daddr; |
407 | uh = skb->h.uh; | 429 | uh = skb->h.uh; |
408 | } | 430 | } |
409 | 431 | ||
410 | if (skb->ip_summed == CHECKSUM_COMPLETE && | 432 | if (udp6_csum_init(skb, uh)) |
411 | !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) | 433 | goto discard; |
412 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
413 | 434 | ||
414 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | 435 | } else { /* UDP-Lite validates cscov. */ |
415 | skb->csum = ~csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, 0); | 436 | if (udplite6_csum_init(skb, uh)) |
437 | goto discard; | ||
438 | } | ||
416 | 439 | ||
417 | /* | 440 | /* |
418 | * Multicast receive code | 441 | * Multicast receive code |
419 | */ | 442 | */ |
420 | if (ipv6_addr_is_multicast(daddr)) { | 443 | if (ipv6_addr_is_multicast(daddr)) |
421 | udpv6_mcast_deliver(uh, saddr, daddr, skb); | 444 | return __udp6_lib_mcast_deliver(skb, saddr, daddr, udptable); |
422 | return 0; | ||
423 | } | ||
424 | 445 | ||
425 | /* Unicast */ | 446 | /* Unicast */ |
426 | 447 | ||
@@ -428,15 +449,16 @@ static int udpv6_rcv(struct sk_buff **pskb) | |||
428 | * check socket cache ... must talk to Alan about his plans | 449 | * check socket cache ... must talk to Alan about his plans |
429 | * for sock caches... i'll skip this for now. | 450 | * for sock caches... i'll skip this for now. |
430 | */ | 451 | */ |
431 | sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest, inet6_iif(skb)); | 452 | sk = __udp6_lib_lookup(saddr, uh->source, |
453 | daddr, uh->dest, inet6_iif(skb), udptable); | ||
432 | 454 | ||
433 | if (sk == NULL) { | 455 | if (sk == NULL) { |
434 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 456 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
435 | goto discard; | 457 | goto discard; |
436 | 458 | ||
437 | if (skb_checksum_complete(skb)) | 459 | if (udp_lib_checksum_complete(skb)) |
438 | goto discard; | 460 | goto discard; |
439 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS); | 461 | UDP6_INC_STATS_BH(UDP_MIB_NOPORTS, is_udplite); |
440 | 462 | ||
441 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); | 463 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev); |
442 | 464 | ||
@@ -451,14 +473,20 @@ static int udpv6_rcv(struct sk_buff **pskb) | |||
451 | return(0); | 473 | return(0); |
452 | 474 | ||
453 | short_packet: | 475 | short_packet: |
454 | if (net_ratelimit()) | 476 | LIMIT_NETDEBUG(KERN_DEBUG "UDP%sv6: short packet: %d/%u\n", |
455 | printk(KERN_DEBUG "UDP: short packet: %d/%u\n", ulen, skb->len); | 477 | is_udplite? "-Lite" : "", ulen, skb->len); |
456 | 478 | ||
457 | discard: | 479 | discard: |
458 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS); | 480 | UDP6_INC_STATS_BH(UDP_MIB_INERRORS, is_udplite); |
459 | kfree_skb(skb); | 481 | kfree_skb(skb); |
460 | return(0); | 482 | return(0); |
461 | } | 483 | } |
484 | |||
485 | static __inline__ int udpv6_rcv(struct sk_buff **pskb) | ||
486 | { | ||
487 | return __udp6_lib_rcv(pskb, udp_hash, 0); | ||
488 | } | ||
489 | |||
462 | /* | 490 | /* |
463 | * Throw away all pending data and cancel the corking. Socket is locked. | 491 | * Throw away all pending data and cancel the corking. Socket is locked. |
464 | */ | 492 | */ |
@@ -477,13 +505,15 @@ static void udp_v6_flush_pending_frames(struct sock *sk) | |||
477 | * Sending | 505 | * Sending |
478 | */ | 506 | */ |
479 | 507 | ||
480 | static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) | 508 | static int udp_v6_push_pending_frames(struct sock *sk) |
481 | { | 509 | { |
482 | struct sk_buff *skb; | 510 | struct sk_buff *skb; |
483 | struct udphdr *uh; | 511 | struct udphdr *uh; |
512 | struct udp_sock *up = udp_sk(sk); | ||
484 | struct inet_sock *inet = inet_sk(sk); | 513 | struct inet_sock *inet = inet_sk(sk); |
485 | struct flowi *fl = &inet->cork.fl; | 514 | struct flowi *fl = &inet->cork.fl; |
486 | int err = 0; | 515 | int err = 0; |
516 | __wsum csum = 0; | ||
487 | 517 | ||
488 | /* Grab the skbuff where UDP header space exists. */ | 518 | /* Grab the skbuff where UDP header space exists. */ |
489 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) | 519 | if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) |
@@ -498,35 +528,17 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) | |||
498 | uh->len = htons(up->len); | 528 | uh->len = htons(up->len); |
499 | uh->check = 0; | 529 | uh->check = 0; |
500 | 530 | ||
501 | if (sk->sk_no_check == UDP_CSUM_NOXMIT) { | 531 | if (up->pcflag) |
502 | skb->ip_summed = CHECKSUM_NONE; | 532 | csum = udplite_csum_outgoing(sk, skb); |
503 | goto send; | 533 | else |
504 | } | 534 | csum = udp_csum_outgoing(sk, skb); |
505 | |||
506 | if (skb_queue_len(&sk->sk_write_queue) == 1) { | ||
507 | skb->csum = csum_partial((char *)uh, | ||
508 | sizeof(struct udphdr), skb->csum); | ||
509 | uh->check = csum_ipv6_magic(&fl->fl6_src, | ||
510 | &fl->fl6_dst, | ||
511 | up->len, fl->proto, skb->csum); | ||
512 | } else { | ||
513 | u32 tmp_csum = 0; | ||
514 | |||
515 | skb_queue_walk(&sk->sk_write_queue, skb) { | ||
516 | tmp_csum = csum_add(tmp_csum, skb->csum); | ||
517 | } | ||
518 | tmp_csum = csum_partial((char *)uh, | ||
519 | sizeof(struct udphdr), tmp_csum); | ||
520 | tmp_csum = csum_ipv6_magic(&fl->fl6_src, | ||
521 | &fl->fl6_dst, | ||
522 | up->len, fl->proto, tmp_csum); | ||
523 | uh->check = tmp_csum; | ||
524 | 535 | ||
525 | } | 536 | /* add protocol-dependent pseudo-header */ |
537 | uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, | ||
538 | up->len, fl->proto, csum ); | ||
526 | if (uh->check == 0) | 539 | if (uh->check == 0) |
527 | uh->check = -1; | 540 | uh->check = CSUM_MANGLED_0; |
528 | 541 | ||
529 | send: | ||
530 | err = ip6_push_pending_frames(sk); | 542 | err = ip6_push_pending_frames(sk); |
531 | out: | 543 | out: |
532 | up->len = 0; | 544 | up->len = 0; |
@@ -534,7 +546,7 @@ out: | |||
534 | return err; | 546 | return err; |
535 | } | 547 | } |
536 | 548 | ||
537 | static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | 549 | int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, |
538 | struct msghdr *msg, size_t len) | 550 | struct msghdr *msg, size_t len) |
539 | { | 551 | { |
540 | struct ipv6_txoptions opt_space; | 552 | struct ipv6_txoptions opt_space; |
@@ -554,6 +566,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
554 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 566 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
555 | int err; | 567 | int err; |
556 | int connected = 0; | 568 | int connected = 0; |
569 | int is_udplite = up->pcflag; | ||
570 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); | ||
557 | 571 | ||
558 | /* destination address check */ | 572 | /* destination address check */ |
559 | if (sin6) { | 573 | if (sin6) { |
@@ -694,7 +708,7 @@ do_udp_sendmsg: | |||
694 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | 708 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
695 | opt = ipv6_fixup_options(&opt_space, opt); | 709 | opt = ipv6_fixup_options(&opt_space, opt); |
696 | 710 | ||
697 | fl.proto = IPPROTO_UDP; | 711 | fl.proto = sk->sk_protocol; |
698 | ipv6_addr_copy(&fl.fl6_dst, daddr); | 712 | ipv6_addr_copy(&fl.fl6_dst, daddr); |
699 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) | 713 | if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) |
700 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); | 714 | ipv6_addr_copy(&fl.fl6_src, &np->saddr); |
@@ -761,14 +775,15 @@ back_from_confirm: | |||
761 | 775 | ||
762 | do_append_data: | 776 | do_append_data: |
763 | up->len += ulen; | 777 | up->len += ulen; |
764 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, | 778 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
779 | err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen, | ||
765 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, | 780 | sizeof(struct udphdr), hlimit, tclass, opt, &fl, |
766 | (struct rt6_info*)dst, | 781 | (struct rt6_info*)dst, |
767 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 782 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
768 | if (err) | 783 | if (err) |
769 | udp_v6_flush_pending_frames(sk); | 784 | udp_v6_flush_pending_frames(sk); |
770 | else if (!corkreq) | 785 | else if (!corkreq) |
771 | err = udp_v6_push_pending_frames(sk, up); | 786 | err = udp_v6_push_pending_frames(sk); |
772 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | 787 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) |
773 | up->pending = 0; | 788 | up->pending = 0; |
774 | 789 | ||
@@ -793,7 +808,7 @@ do_append_data: | |||
793 | out: | 808 | out: |
794 | fl6_sock_release(flowlabel); | 809 | fl6_sock_release(flowlabel); |
795 | if (!err) { | 810 | if (!err) { |
796 | UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); | 811 | UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS, is_udplite); |
797 | return len; | 812 | return len; |
798 | } | 813 | } |
799 | /* | 814 | /* |
@@ -804,7 +819,7 @@ out: | |||
804 | * seems like overkill. | 819 | * seems like overkill. |
805 | */ | 820 | */ |
806 | if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { | 821 | if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { |
807 | UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); | 822 | UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS, is_udplite); |
808 | } | 823 | } |
809 | return err; | 824 | return err; |
810 | 825 | ||
@@ -816,7 +831,7 @@ do_confirm: | |||
816 | goto out; | 831 | goto out; |
817 | } | 832 | } |
818 | 833 | ||
819 | static int udpv6_destroy_sock(struct sock *sk) | 834 | int udpv6_destroy_sock(struct sock *sk) |
820 | { | 835 | { |
821 | lock_sock(sk); | 836 | lock_sock(sk); |
822 | udp_v6_flush_pending_frames(sk); | 837 | udp_v6_flush_pending_frames(sk); |
@@ -830,119 +845,41 @@ static int udpv6_destroy_sock(struct sock *sk) | |||
830 | /* | 845 | /* |
831 | * Socket option code for UDP | 846 | * Socket option code for UDP |
832 | */ | 847 | */ |
833 | static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, | 848 | int udpv6_setsockopt(struct sock *sk, int level, int optname, |
834 | char __user *optval, int optlen) | 849 | char __user *optval, int optlen) |
835 | { | ||
836 | struct udp_sock *up = udp_sk(sk); | ||
837 | int val; | ||
838 | int err = 0; | ||
839 | |||
840 | if(optlen<sizeof(int)) | ||
841 | return -EINVAL; | ||
842 | |||
843 | if (get_user(val, (int __user *)optval)) | ||
844 | return -EFAULT; | ||
845 | |||
846 | switch(optname) { | ||
847 | case UDP_CORK: | ||
848 | if (val != 0) { | ||
849 | up->corkflag = 1; | ||
850 | } else { | ||
851 | up->corkflag = 0; | ||
852 | lock_sock(sk); | ||
853 | udp_v6_push_pending_frames(sk, up); | ||
854 | release_sock(sk); | ||
855 | } | ||
856 | break; | ||
857 | |||
858 | case UDP_ENCAP: | ||
859 | switch (val) { | ||
860 | case 0: | ||
861 | up->encap_type = val; | ||
862 | break; | ||
863 | default: | ||
864 | err = -ENOPROTOOPT; | ||
865 | break; | ||
866 | } | ||
867 | break; | ||
868 | |||
869 | default: | ||
870 | err = -ENOPROTOOPT; | ||
871 | break; | ||
872 | }; | ||
873 | |||
874 | return err; | ||
875 | } | ||
876 | |||
877 | static int udpv6_setsockopt(struct sock *sk, int level, int optname, | ||
878 | char __user *optval, int optlen) | ||
879 | { | 850 | { |
880 | if (level != SOL_UDP) | 851 | if (level == SOL_UDP || level == SOL_UDPLITE) |
881 | return ipv6_setsockopt(sk, level, optname, optval, optlen); | 852 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
882 | return do_udpv6_setsockopt(sk, level, optname, optval, optlen); | 853 | udp_v6_push_pending_frames); |
854 | return ipv6_setsockopt(sk, level, optname, optval, optlen); | ||
883 | } | 855 | } |
884 | 856 | ||
885 | #ifdef CONFIG_COMPAT | 857 | #ifdef CONFIG_COMPAT |
886 | static int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, | 858 | int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, |
887 | char __user *optval, int optlen) | 859 | char __user *optval, int optlen) |
888 | { | 860 | { |
889 | if (level != SOL_UDP) | 861 | if (level == SOL_UDP || level == SOL_UDPLITE) |
890 | return compat_ipv6_setsockopt(sk, level, optname, | 862 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
891 | optval, optlen); | 863 | udp_v6_push_pending_frames); |
892 | return do_udpv6_setsockopt(sk, level, optname, optval, optlen); | 864 | return compat_ipv6_setsockopt(sk, level, optname, optval, optlen); |
893 | } | 865 | } |
894 | #endif | 866 | #endif |
895 | 867 | ||
896 | static int do_udpv6_getsockopt(struct sock *sk, int level, int optname, | 868 | int udpv6_getsockopt(struct sock *sk, int level, int optname, |
897 | char __user *optval, int __user *optlen) | 869 | char __user *optval, int __user *optlen) |
898 | { | ||
899 | struct udp_sock *up = udp_sk(sk); | ||
900 | int val, len; | ||
901 | |||
902 | if(get_user(len,optlen)) | ||
903 | return -EFAULT; | ||
904 | |||
905 | len = min_t(unsigned int, len, sizeof(int)); | ||
906 | |||
907 | if(len < 0) | ||
908 | return -EINVAL; | ||
909 | |||
910 | switch(optname) { | ||
911 | case UDP_CORK: | ||
912 | val = up->corkflag; | ||
913 | break; | ||
914 | |||
915 | case UDP_ENCAP: | ||
916 | val = up->encap_type; | ||
917 | break; | ||
918 | |||
919 | default: | ||
920 | return -ENOPROTOOPT; | ||
921 | }; | ||
922 | |||
923 | if(put_user(len, optlen)) | ||
924 | return -EFAULT; | ||
925 | if(copy_to_user(optval, &val,len)) | ||
926 | return -EFAULT; | ||
927 | return 0; | ||
928 | } | ||
929 | |||
930 | static int udpv6_getsockopt(struct sock *sk, int level, int optname, | ||
931 | char __user *optval, int __user *optlen) | ||
932 | { | 870 | { |
933 | if (level != SOL_UDP) | 871 | if (level == SOL_UDP || level == SOL_UDPLITE) |
934 | return ipv6_getsockopt(sk, level, optname, optval, optlen); | 872 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
935 | return do_udpv6_getsockopt(sk, level, optname, optval, optlen); | 873 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
936 | } | 874 | } |
937 | 875 | ||
938 | #ifdef CONFIG_COMPAT | 876 | #ifdef CONFIG_COMPAT |
939 | static int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, | 877 | int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, |
940 | char __user *optval, int __user *optlen) | 878 | char __user *optval, int __user *optlen) |
941 | { | 879 | { |
942 | if (level != SOL_UDP) | 880 | if (level == SOL_UDP || level == SOL_UDPLITE) |
943 | return compat_ipv6_getsockopt(sk, level, optname, | 881 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
944 | optval, optlen); | 882 | return compat_ipv6_getsockopt(sk, level, optname, optval, optlen); |
945 | return do_udpv6_getsockopt(sk, level, optname, optval, optlen); | ||
946 | } | 883 | } |
947 | #endif | 884 | #endif |
948 | 885 | ||
@@ -983,7 +920,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
983 | atomic_read(&sp->sk_refcnt), sp); | 920 | atomic_read(&sp->sk_refcnt), sp); |
984 | } | 921 | } |
985 | 922 | ||
986 | static int udp6_seq_show(struct seq_file *seq, void *v) | 923 | int udp6_seq_show(struct seq_file *seq, void *v) |
987 | { | 924 | { |
988 | if (v == SEQ_START_TOKEN) | 925 | if (v == SEQ_START_TOKEN) |
989 | seq_printf(seq, | 926 | seq_printf(seq, |
@@ -1002,6 +939,7 @@ static struct udp_seq_afinfo udp6_seq_afinfo = { | |||
1002 | .owner = THIS_MODULE, | 939 | .owner = THIS_MODULE, |
1003 | .name = "udp6", | 940 | .name = "udp6", |
1004 | .family = AF_INET6, | 941 | .family = AF_INET6, |
942 | .hashtable = udp_hash, | ||
1005 | .seq_show = udp6_seq_show, | 943 | .seq_show = udp6_seq_show, |
1006 | .seq_fops = &udp6_seq_fops, | 944 | .seq_fops = &udp6_seq_fops, |
1007 | }; | 945 | }; |
@@ -1021,7 +959,7 @@ void udp6_proc_exit(void) { | |||
1021 | struct proto udpv6_prot = { | 959 | struct proto udpv6_prot = { |
1022 | .name = "UDPv6", | 960 | .name = "UDPv6", |
1023 | .owner = THIS_MODULE, | 961 | .owner = THIS_MODULE, |
1024 | .close = udpv6_close, | 962 | .close = udp_lib_close, |
1025 | .connect = ip6_datagram_connect, | 963 | .connect = ip6_datagram_connect, |
1026 | .disconnect = udp_disconnect, | 964 | .disconnect = udp_disconnect, |
1027 | .ioctl = udp_ioctl, | 965 | .ioctl = udp_ioctl, |
@@ -1031,8 +969,8 @@ struct proto udpv6_prot = { | |||
1031 | .sendmsg = udpv6_sendmsg, | 969 | .sendmsg = udpv6_sendmsg, |
1032 | .recvmsg = udpv6_recvmsg, | 970 | .recvmsg = udpv6_recvmsg, |
1033 | .backlog_rcv = udpv6_queue_rcv_skb, | 971 | .backlog_rcv = udpv6_queue_rcv_skb, |
1034 | .hash = udp_v6_hash, | 972 | .hash = udp_lib_hash, |
1035 | .unhash = udp_v6_unhash, | 973 | .unhash = udp_lib_unhash, |
1036 | .get_port = udp_v6_get_port, | 974 | .get_port = udp_v6_get_port, |
1037 | .obj_size = sizeof(struct udp6_sock), | 975 | .obj_size = sizeof(struct udp6_sock), |
1038 | #ifdef CONFIG_COMPAT | 976 | #ifdef CONFIG_COMPAT |
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h new file mode 100644 index 000000000000..ec9878899128 --- /dev/null +++ b/net/ipv6/udp_impl.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef _UDP6_IMPL_H | ||
2 | #define _UDP6_IMPL_H | ||
3 | #include <net/udp.h> | ||
4 | #include <net/udplite.h> | ||
5 | #include <net/protocol.h> | ||
6 | #include <net/addrconf.h> | ||
7 | #include <net/inet_common.h> | ||
8 | |||
9 | extern int __udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int ); | ||
10 | extern void __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, | ||
11 | int , int , int , __be32 , struct hlist_head []); | ||
12 | |||
13 | extern int udpv6_getsockopt(struct sock *sk, int level, int optname, | ||
14 | char __user *optval, int __user *optlen); | ||
15 | extern int udpv6_setsockopt(struct sock *sk, int level, int optname, | ||
16 | char __user *optval, int optlen); | ||
17 | #ifdef CONFIG_COMPAT | ||
18 | extern int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, | ||
19 | char __user *optval, int optlen); | ||
20 | extern int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, | ||
21 | char __user *optval, int __user *optlen); | ||
22 | #endif | ||
23 | extern int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | ||
24 | struct msghdr *msg, size_t len); | ||
25 | extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, | ||
26 | struct msghdr *msg, size_t len, | ||
27 | int noblock, int flags, int *addr_len); | ||
28 | extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); | ||
29 | extern int udpv6_destroy_sock(struct sock *sk); | ||
30 | |||
31 | #ifdef CONFIG_PROC_FS | ||
32 | extern int udp6_seq_show(struct seq_file *seq, void *v); | ||
33 | #endif | ||
34 | #endif /* _UDP6_IMPL_H */ | ||
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c new file mode 100644 index 000000000000..629f97162fbc --- /dev/null +++ b/net/ipv6/udplite.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * UDPLITEv6 An implementation of the UDP-Lite protocol over IPv6. | ||
3 | * See also net/ipv4/udplite.c | ||
4 | * | ||
5 | * Version: $Id: udplite.c,v 1.9 2006/10/19 08:28:10 gerrit Exp $ | ||
6 | * | ||
7 | * Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk> | ||
8 | * | ||
9 | * Changes: | ||
10 | * Fixes: | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | #include "udp_impl.h" | ||
17 | |||
18 | DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; | ||
19 | |||
20 | static int udplitev6_rcv(struct sk_buff **pskb) | ||
21 | { | ||
22 | return __udp6_lib_rcv(pskb, udplite_hash, 1); | ||
23 | } | ||
24 | |||
25 | static void udplitev6_err(struct sk_buff *skb, | ||
26 | struct inet6_skb_parm *opt, | ||
27 | int type, int code, int offset, __be32 info) | ||
28 | { | ||
29 | return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); | ||
30 | } | ||
31 | |||
32 | static struct inet6_protocol udplitev6_protocol = { | ||
33 | .handler = udplitev6_rcv, | ||
34 | .err_handler = udplitev6_err, | ||
35 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | ||
36 | }; | ||
37 | |||
38 | static int udplite_v6_get_port(struct sock *sk, unsigned short snum) | ||
39 | { | ||
40 | return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); | ||
41 | } | ||
42 | |||
43 | struct proto udplitev6_prot = { | ||
44 | .name = "UDPLITEv6", | ||
45 | .owner = THIS_MODULE, | ||
46 | .close = udp_lib_close, | ||
47 | .connect = ip6_datagram_connect, | ||
48 | .disconnect = udp_disconnect, | ||
49 | .ioctl = udp_ioctl, | ||
50 | .init = udplite_sk_init, | ||
51 | .destroy = udpv6_destroy_sock, | ||
52 | .setsockopt = udpv6_setsockopt, | ||
53 | .getsockopt = udpv6_getsockopt, | ||
54 | .sendmsg = udpv6_sendmsg, | ||
55 | .recvmsg = udpv6_recvmsg, | ||
56 | .backlog_rcv = udpv6_queue_rcv_skb, | ||
57 | .hash = udp_lib_hash, | ||
58 | .unhash = udp_lib_unhash, | ||
59 | .get_port = udplite_v6_get_port, | ||
60 | .obj_size = sizeof(struct udp6_sock), | ||
61 | #ifdef CONFIG_COMPAT | ||
62 | .compat_setsockopt = compat_udpv6_setsockopt, | ||
63 | .compat_getsockopt = compat_udpv6_getsockopt, | ||
64 | #endif | ||
65 | }; | ||
66 | |||
67 | static struct inet_protosw udplite6_protosw = { | ||
68 | .type = SOCK_DGRAM, | ||
69 | .protocol = IPPROTO_UDPLITE, | ||
70 | .prot = &udplitev6_prot, | ||
71 | .ops = &inet6_dgram_ops, | ||
72 | .capability = -1, | ||
73 | .no_check = 0, | ||
74 | .flags = INET_PROTOSW_PERMANENT, | ||
75 | }; | ||
76 | |||
77 | void __init udplitev6_init(void) | ||
78 | { | ||
79 | if (inet6_add_protocol(&udplitev6_protocol, IPPROTO_UDPLITE) < 0) | ||
80 | printk(KERN_ERR "%s: Could not register.\n", __FUNCTION__); | ||
81 | |||
82 | inet6_register_protosw(&udplite6_protosw); | ||
83 | } | ||
84 | |||
85 | #ifdef CONFIG_PROC_FS | ||
86 | static struct file_operations udplite6_seq_fops; | ||
87 | static struct udp_seq_afinfo udplite6_seq_afinfo = { | ||
88 | .owner = THIS_MODULE, | ||
89 | .name = "udplite6", | ||
90 | .family = AF_INET6, | ||
91 | .hashtable = udplite_hash, | ||
92 | .seq_show = udp6_seq_show, | ||
93 | .seq_fops = &udplite6_seq_fops, | ||
94 | }; | ||
95 | |||
96 | int __init udplite6_proc_init(void) | ||
97 | { | ||
98 | return udp_proc_register(&udplite6_seq_afinfo); | ||
99 | } | ||
100 | |||
101 | void udplite6_proc_exit(void) | ||
102 | { | ||
103 | udp_proc_unregister(&udplite6_seq_afinfo); | ||
104 | } | ||
105 | #endif | ||
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index d400f8fae129..8dffd4daae9c 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -274,11 +274,12 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) | |||
274 | break; | 274 | break; |
275 | 275 | ||
276 | case IPPROTO_UDP: | 276 | case IPPROTO_UDP: |
277 | case IPPROTO_UDPLITE: | ||
277 | case IPPROTO_TCP: | 278 | case IPPROTO_TCP: |
278 | case IPPROTO_SCTP: | 279 | case IPPROTO_SCTP: |
279 | case IPPROTO_DCCP: | 280 | case IPPROTO_DCCP: |
280 | if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { | 281 | if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { |
281 | u16 *ports = (u16 *)exthdr; | 282 | __be16 *ports = (__be16 *)exthdr; |
282 | 283 | ||
283 | fl->fl_ip_sport = ports[0]; | 284 | fl->fl_ip_sport = ports[0]; |
284 | fl->fl_ip_dport = ports[1]; | 285 | fl->fl_ip_dport = ports[1]; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 7931e4f898d4..01a5c52a2be3 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -62,7 +62,7 @@ static unsigned inline xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) | |||
62 | { | 62 | { |
63 | unsigned h; | 63 | unsigned h; |
64 | 64 | ||
65 | h = addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]; | 65 | h = (__force u32)(addr->a6[0] ^ addr->a6[1] ^ addr->a6[2] ^ addr->a6[3]); |
66 | h ^= h >> 16; | 66 | h ^= h >> 16; |
67 | h ^= h >> 8; | 67 | h ^= h >> 8; |
68 | h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1; | 68 | h &= XFRM6_TUNNEL_SPI_BYADDR_HSIZE - 1; |
@@ -126,7 +126,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) | |||
126 | return NULL; | 126 | return NULL; |
127 | } | 127 | } |
128 | 128 | ||
129 | u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) | 129 | __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr) |
130 | { | 130 | { |
131 | struct xfrm6_tunnel_spi *x6spi; | 131 | struct xfrm6_tunnel_spi *x6spi; |
132 | u32 spi; | 132 | u32 spi; |
@@ -196,7 +196,7 @@ out: | |||
196 | return spi; | 196 | return spi; |
197 | } | 197 | } |
198 | 198 | ||
199 | u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) | 199 | __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr) |
200 | { | 200 | { |
201 | struct xfrm6_tunnel_spi *x6spi; | 201 | struct xfrm6_tunnel_spi *x6spi; |
202 | u32 spi; | 202 | u32 spi; |
@@ -265,7 +265,7 @@ static int xfrm6_tunnel_rcv(struct sk_buff *skb) | |||
265 | } | 265 | } |
266 | 266 | ||
267 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 267 | static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
268 | int type, int code, int offset, __u32 info) | 268 | int type, int code, int offset, __be32 info) |
269 | { | 269 | { |
270 | /* xfrm6_tunnel native err handling */ | 270 | /* xfrm6_tunnel native err handling */ |
271 | switch (type) { | 271 | switch (type) { |