diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 4 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 2 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Kconfig | 11 | ||||
| -rw-r--r-- | net/ipv6/netfilter/Makefile | 2 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 4 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 52 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_ah.c | 81 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_dst.c | 88 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_esp.c | 73 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_frag.c | 90 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_hbh.c | 88 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6t_rt.c | 83 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 2 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 18 | ||||
| -rw-r--r-- | net/ipv6/udp.c | 27 |
16 files changed, 140 insertions, 487 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 2fea3f4402a0..a970b4727ce8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -1806,7 +1806,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) | |||
| 1806 | } | 1806 | } |
| 1807 | 1807 | ||
| 1808 | for (dev = dev_base; dev != NULL; dev = dev->next) { | 1808 | for (dev = dev_base; dev != NULL; dev = dev->next) { |
| 1809 | struct in_device * in_dev = __in_dev_get(dev); | 1809 | struct in_device * in_dev = __in_dev_get_rtnl(dev); |
| 1810 | if (in_dev && (dev->flags & IFF_UP)) { | 1810 | if (in_dev && (dev->flags & IFF_UP)) { |
| 1811 | struct in_ifaddr * ifa; | 1811 | struct in_ifaddr * ifa; |
| 1812 | 1812 | ||
| @@ -3520,6 +3520,8 @@ int __init addrconf_init(void) | |||
| 3520 | if (err) | 3520 | if (err) |
| 3521 | return err; | 3521 | return err; |
| 3522 | 3522 | ||
| 3523 | ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev); | ||
| 3524 | |||
| 3523 | register_netdevice_notifier(&ipv6_dev_notf); | 3525 | register_netdevice_notifier(&ipv6_dev_notf); |
| 3524 | 3526 | ||
| 3525 | #ifdef CONFIG_IPV6_PRIVACY | 3527 | #ifdef CONFIG_IPV6_PRIVACY |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 2f589f24c093..563b442ffab8 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -666,7 +666,7 @@ slow_path: | |||
| 666 | */ | 666 | */ |
| 667 | fh->nexthdr = nexthdr; | 667 | fh->nexthdr = nexthdr; |
| 668 | fh->reserved = 0; | 668 | fh->reserved = 0; |
| 669 | if (frag_id) { | 669 | if (!frag_id) { |
| 670 | ipv6_select_ident(skb, fh); | 670 | ipv6_select_ident(skb, fh); |
| 671 | frag_id = fh->identification; | 671 | frag_id = fh->identification; |
| 672 | } else | 672 | } else |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 29fed6e58d0a..519899fb11d5 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -1968,7 +1968,7 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc) | |||
| 1968 | } | 1968 | } |
| 1969 | pmc->mca_sources = NULL; | 1969 | pmc->mca_sources = NULL; |
| 1970 | pmc->mca_sfmode = MCAST_EXCLUDE; | 1970 | pmc->mca_sfmode = MCAST_EXCLUDE; |
| 1971 | pmc->mca_sfcount[MCAST_EXCLUDE] = 0; | 1971 | pmc->mca_sfcount[MCAST_INCLUDE] = 0; |
| 1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; | 1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; |
| 1973 | } | 1973 | } |
| 1974 | 1974 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 216fbe1ac65c..bb7ccfe33f23 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -209,6 +209,17 @@ config IP6_NF_TARGET_REJECT | |||
| 209 | 209 | ||
| 210 | To compile it as a module, choose M here. If unsure, say N. | 210 | To compile it as a module, choose M here. If unsure, say N. |
| 211 | 211 | ||
| 212 | config IP6_NF_TARGET_NFQUEUE | ||
| 213 | tristate "NFQUEUE Target Support" | ||
| 214 | depends on IP_NF_IPTABLES | ||
| 215 | help | ||
| 216 | This Target replaced the old obsolete QUEUE target. | ||
| 217 | |||
| 218 | As opposed to QUEUE, it supports 65535 different queues, | ||
| 219 | not just one. | ||
| 220 | |||
| 221 | To compile it as a module, choose M here. If unsure, say N. | ||
| 222 | |||
| 212 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then | 223 | # if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then |
| 213 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER | 224 | # dep_tristate ' REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER |
| 214 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then | 225 | # if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index bd9a16a5cbba..2b2c370e8b1c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -21,9 +21,9 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | |||
| 21 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 21 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
| 22 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o | 22 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o |
| 23 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o | 23 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o |
| 24 | obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o | ||
| 24 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 25 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
| 25 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 26 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
| 26 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 27 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
| 27 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o |
| 28 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 29 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
| 29 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += ip6t_NFQUEUE.o | ||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index aa11cf366efa..5027bbe6415e 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
| @@ -238,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) | |||
| 238 | 238 | ||
| 239 | pmsg->packet_id = (unsigned long )entry; | 239 | pmsg->packet_id = (unsigned long )entry; |
| 240 | pmsg->data_len = data_len; | 240 | pmsg->data_len = data_len; |
| 241 | pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; | 241 | pmsg->timestamp_sec = entry->skb->tstamp.off_sec; |
| 242 | pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; | 242 | pmsg->timestamp_usec = entry->skb->tstamp.off_usec; |
| 243 | pmsg->mark = entry->skb->nfmark; | 243 | pmsg->mark = entry->skb->nfmark; |
| 244 | pmsg->hook = entry->info->hook; | 244 | pmsg->hook = entry->info->hook; |
| 245 | pmsg->hw_protocol = entry->skb->protocol; | 245 | pmsg->hw_protocol = entry->skb->protocol; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1cb8adb2787f..2da514b16d95 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -1955,6 +1955,57 @@ static void __exit fini(void) | |||
| 1955 | #endif | 1955 | #endif |
| 1956 | } | 1956 | } |
| 1957 | 1957 | ||
| 1958 | /* | ||
| 1959 | * find specified header up to transport protocol header. | ||
| 1960 | * If found target header, the offset to the header is set to *offset | ||
| 1961 | * and return 0. otherwise, return -1. | ||
| 1962 | * | ||
| 1963 | * Notes: - non-1st Fragment Header isn't skipped. | ||
| 1964 | * - ESP header isn't skipped. | ||
| 1965 | * - The target header may be trancated. | ||
| 1966 | */ | ||
| 1967 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) | ||
| 1968 | { | ||
| 1969 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | ||
| 1970 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 1971 | unsigned int len = skb->len - start; | ||
| 1972 | |||
| 1973 | while (nexthdr != target) { | ||
| 1974 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 1975 | unsigned int hdrlen; | ||
| 1976 | |||
| 1977 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) | ||
| 1978 | return -1; | ||
| 1979 | hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); | ||
| 1980 | if (hp == NULL) | ||
| 1981 | return -1; | ||
| 1982 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 1983 | unsigned short _frag_off, *fp; | ||
| 1984 | fp = skb_header_pointer(skb, | ||
| 1985 | start+offsetof(struct frag_hdr, | ||
| 1986 | frag_off), | ||
| 1987 | sizeof(_frag_off), | ||
| 1988 | &_frag_off); | ||
| 1989 | if (fp == NULL) | ||
| 1990 | return -1; | ||
| 1991 | |||
| 1992 | if (ntohs(*fp) & ~0x7) | ||
| 1993 | return -1; | ||
| 1994 | hdrlen = 8; | ||
| 1995 | } else if (nexthdr == NEXTHDR_AUTH) | ||
| 1996 | hdrlen = (hp->hdrlen + 2) << 2; | ||
| 1997 | else | ||
| 1998 | hdrlen = ipv6_optlen(hp); | ||
| 1999 | |||
| 2000 | nexthdr = hp->nexthdr; | ||
| 2001 | len -= hdrlen; | ||
| 2002 | start += hdrlen; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | *offset = start; | ||
| 2006 | return 0; | ||
| 2007 | } | ||
| 2008 | |||
| 1958 | EXPORT_SYMBOL(ip6t_register_table); | 2009 | EXPORT_SYMBOL(ip6t_register_table); |
| 1959 | EXPORT_SYMBOL(ip6t_unregister_table); | 2010 | EXPORT_SYMBOL(ip6t_unregister_table); |
| 1960 | EXPORT_SYMBOL(ip6t_do_table); | 2011 | EXPORT_SYMBOL(ip6t_do_table); |
| @@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); | |||
| 1963 | EXPORT_SYMBOL(ip6t_register_target); | 2014 | EXPORT_SYMBOL(ip6t_register_target); |
| 1964 | EXPORT_SYMBOL(ip6t_unregister_target); | 2015 | EXPORT_SYMBOL(ip6t_unregister_target); |
| 1965 | EXPORT_SYMBOL(ip6t_ext_hdr); | 2016 | EXPORT_SYMBOL(ip6t_ext_hdr); |
| 2017 | EXPORT_SYMBOL(ipv6_find_hdr); | ||
| 1966 | 2018 | ||
| 1967 | module_init(init); | 2019 | module_init(init); |
| 1968 | module_exit(fini); | 2020 | module_exit(fini); |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index d5b94f142bba..dde37793d20b 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
| @@ -48,92 +48,21 @@ match(const struct sk_buff *skb, | |||
| 48 | unsigned int protoff, | 48 | unsigned int protoff, |
| 49 | int *hotdrop) | 49 | int *hotdrop) |
| 50 | { | 50 | { |
| 51 | struct ip_auth_hdr *ah = NULL, _ah; | 51 | struct ip_auth_hdr *ah, _ah; |
| 52 | const struct ip6t_ah *ahinfo = matchinfo; | 52 | const struct ip6t_ah *ahinfo = matchinfo; |
| 53 | unsigned int temp; | ||
| 54 | int len; | ||
| 55 | u8 nexthdr; | ||
| 56 | unsigned int ptr; | 53 | unsigned int ptr; |
| 57 | unsigned int hdrlen = 0; | 54 | unsigned int hdrlen = 0; |
| 58 | 55 | ||
| 59 | /*DEBUGP("IPv6 AH entered\n");*/ | 56 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0) |
| 60 | /* if (opt->auth == 0) return 0; | ||
| 61 | * It does not filled on output */ | ||
| 62 | |||
| 63 | /* type of the 1st exthdr */ | ||
| 64 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 65 | /* pointer to the 1st exthdr */ | ||
| 66 | ptr = sizeof(struct ipv6hdr); | ||
| 67 | /* available length */ | ||
| 68 | len = skb->len - ptr; | ||
| 69 | temp = 0; | ||
| 70 | |||
| 71 | while (ip6t_ext_hdr(nexthdr)) { | ||
| 72 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 73 | |||
| 74 | DEBUGP("ipv6_ah header iteration \n"); | ||
| 75 | |||
| 76 | /* Is there enough space for the next ext header? */ | ||
| 77 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
| 78 | return 0; | ||
| 79 | /* No more exthdr -> evaluate */ | ||
| 80 | if (nexthdr == NEXTHDR_NONE) | ||
| 81 | break; | ||
| 82 | /* ESP -> evaluate */ | ||
| 83 | if (nexthdr == NEXTHDR_ESP) | ||
| 84 | break; | ||
| 85 | |||
| 86 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 87 | BUG_ON(hp == NULL); | ||
| 88 | |||
| 89 | /* Calculate the header length */ | ||
| 90 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
| 91 | hdrlen = 8; | ||
| 92 | else if (nexthdr == NEXTHDR_AUTH) | ||
| 93 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 94 | else | ||
| 95 | hdrlen = ipv6_optlen(hp); | ||
| 96 | |||
| 97 | /* AH -> evaluate */ | ||
| 98 | if (nexthdr == NEXTHDR_AUTH) { | ||
| 99 | temp |= MASK_AH; | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | |||
| 103 | |||
| 104 | /* set the flag */ | ||
| 105 | switch (nexthdr) { | ||
| 106 | case NEXTHDR_HOP: | ||
| 107 | case NEXTHDR_ROUTING: | ||
| 108 | case NEXTHDR_FRAGMENT: | ||
| 109 | case NEXTHDR_AUTH: | ||
| 110 | case NEXTHDR_DEST: | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | nexthdr = hp->nexthdr; | ||
| 118 | len -= hdrlen; | ||
| 119 | ptr += hdrlen; | ||
| 120 | if (ptr > skb->len) { | ||
| 121 | DEBUGP("ipv6_ah: new pointer too large! \n"); | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | /* AH header not found */ | ||
| 127 | if (temp != MASK_AH) | ||
| 128 | return 0; | 57 | return 0; |
| 129 | 58 | ||
| 130 | if (len < sizeof(struct ip_auth_hdr)){ | 59 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
| 60 | if (ah == NULL) { | ||
| 131 | *hotdrop = 1; | 61 | *hotdrop = 1; |
| 132 | return 0; | 62 | return 0; |
| 133 | } | 63 | } |
| 134 | 64 | ||
| 135 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 65 | hdrlen = (ah->hdrlen + 2) << 2; |
| 136 | BUG_ON(ah == NULL); | ||
| 137 | 66 | ||
| 138 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); | 67 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); |
| 139 | DEBUGP("RES %04X ", ah->reserved); | 68 | DEBUGP("RES %04X ", ah->reserved); |
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 540925e4a7a8..c450a635e54b 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c | |||
| @@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
| 63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
| 64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
| 65 | unsigned int temp; | 65 | unsigned int temp; |
| 66 | unsigned int len; | ||
| 67 | u8 nexthdr; | ||
| 68 | unsigned int ptr; | 66 | unsigned int ptr; |
| 69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
| 70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
| @@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
| 72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
| 73 | unsigned int optlen; | 71 | unsigned int optlen; |
| 74 | 72 | ||
| 75 | /* type of the 1st exthdr */ | ||
| 76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 77 | /* pointer to the 1st exthdr */ | ||
| 78 | ptr = sizeof(struct ipv6hdr); | ||
| 79 | /* available length */ | ||
| 80 | len = skb->len - ptr; | ||
| 81 | temp = 0; | ||
| 82 | |||
| 83 | while (ip6t_ext_hdr(nexthdr)) { | ||
| 84 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 85 | |||
| 86 | DEBUGP("ipv6_opts header iteration \n"); | ||
| 87 | |||
| 88 | /* Is there enough space for the next ext header? */ | ||
| 89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
| 90 | return 0; | ||
| 91 | /* No more exthdr -> evaluate */ | ||
| 92 | if (nexthdr == NEXTHDR_NONE) { | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | /* ESP -> evaluate */ | ||
| 96 | if (nexthdr == NEXTHDR_ESP) { | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | |||
| 100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 101 | BUG_ON(hp == NULL); | ||
| 102 | |||
| 103 | /* Calculate the header length */ | ||
| 104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 105 | hdrlen = 8; | ||
| 106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
| 107 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 108 | else | ||
| 109 | hdrlen = ipv6_optlen(hp); | ||
| 110 | |||
| 111 | /* OPTS -> evaluate */ | ||
| 112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
| 113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
| 114 | temp |= MASK_HOPOPTS; | ||
| 115 | #else | 75 | #else |
| 116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
| 117 | temp |= MASK_DSTOPTS; | ||
| 118 | #endif | 77 | #endif |
| 119 | break; | 78 | return 0; |
| 120 | } | ||
| 121 | |||
| 122 | 79 | ||
| 123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
| 124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
| 125 | case NEXTHDR_HOP: | ||
| 126 | case NEXTHDR_ROUTING: | ||
| 127 | case NEXTHDR_FRAGMENT: | ||
| 128 | case NEXTHDR_AUTH: | ||
| 129 | case NEXTHDR_DEST: | ||
| 130 | break; | ||
| 131 | default: | ||
| 132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
| 133 | return 0; | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | |||
| 137 | nexthdr = hp->nexthdr; | ||
| 138 | len -= hdrlen; | ||
| 139 | ptr += hdrlen; | ||
| 140 | if ( ptr > skb->len ) { | ||
| 141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | /* OPTIONS header not found */ | ||
| 147 | #if HOPBYHOP | ||
| 148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
| 149 | #else | ||
| 150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
| 151 | #endif | ||
| 152 | |||
| 153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
| 154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
| 155 | return 0; | 83 | return 0; |
| 156 | } | 84 | } |
| 157 | 85 | ||
| 158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
| 87 | if (skb->len - ptr < hdrlen){ | ||
| 159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
| 160 | return 0; | 89 | return 0; |
| 161 | } | 90 | } |
| 162 | 91 | ||
| 163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
| 164 | BUG_ON(oh == NULL); | ||
| 165 | |||
| 166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
| 167 | 93 | ||
| 168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e39dd236fd8e..24bc0cde43a1 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c | |||
| @@ -48,87 +48,22 @@ match(const struct sk_buff *skb, | |||
| 48 | unsigned int protoff, | 48 | unsigned int protoff, |
| 49 | int *hotdrop) | 49 | int *hotdrop) |
| 50 | { | 50 | { |
| 51 | struct ip_esp_hdr _esp, *eh = NULL; | 51 | struct ip_esp_hdr _esp, *eh; |
| 52 | const struct ip6t_esp *espinfo = matchinfo; | 52 | const struct ip6t_esp *espinfo = matchinfo; |
| 53 | unsigned int temp; | ||
| 54 | int len; | ||
| 55 | u8 nexthdr; | ||
| 56 | unsigned int ptr; | 53 | unsigned int ptr; |
| 57 | 54 | ||
| 58 | /* Make sure this isn't an evil packet */ | 55 | /* Make sure this isn't an evil packet */ |
| 59 | /*DEBUGP("ipv6_esp entered \n");*/ | 56 | /*DEBUGP("ipv6_esp entered \n");*/ |
| 60 | 57 | ||
| 61 | /* type of the 1st exthdr */ | 58 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0) |
| 62 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 63 | /* pointer to the 1st exthdr */ | ||
| 64 | ptr = sizeof(struct ipv6hdr); | ||
| 65 | /* available length */ | ||
| 66 | len = skb->len - ptr; | ||
| 67 | temp = 0; | ||
| 68 | |||
| 69 | while (ip6t_ext_hdr(nexthdr)) { | ||
| 70 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 71 | int hdrlen; | ||
| 72 | |||
| 73 | DEBUGP("ipv6_esp header iteration \n"); | ||
| 74 | |||
| 75 | /* Is there enough space for the next ext header? */ | ||
| 76 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
| 77 | return 0; | ||
| 78 | /* No more exthdr -> evaluate */ | ||
| 79 | if (nexthdr == NEXTHDR_NONE) | ||
| 80 | break; | ||
| 81 | /* ESP -> evaluate */ | ||
| 82 | if (nexthdr == NEXTHDR_ESP) { | ||
| 83 | temp |= MASK_ESP; | ||
| 84 | break; | ||
| 85 | } | ||
| 86 | |||
| 87 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 88 | BUG_ON(hp == NULL); | ||
| 89 | |||
| 90 | /* Calculate the header length */ | ||
| 91 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
| 92 | hdrlen = 8; | ||
| 93 | else if (nexthdr == NEXTHDR_AUTH) | ||
| 94 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 95 | else | ||
| 96 | hdrlen = ipv6_optlen(hp); | ||
| 97 | |||
| 98 | /* set the flag */ | ||
| 99 | switch (nexthdr) { | ||
| 100 | case NEXTHDR_HOP: | ||
| 101 | case NEXTHDR_ROUTING: | ||
| 102 | case NEXTHDR_FRAGMENT: | ||
| 103 | case NEXTHDR_AUTH: | ||
| 104 | case NEXTHDR_DEST: | ||
| 105 | break; | ||
| 106 | default: | ||
| 107 | DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr); | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | nexthdr = hp->nexthdr; | ||
| 112 | len -= hdrlen; | ||
| 113 | ptr += hdrlen; | ||
| 114 | if (ptr > skb->len) { | ||
| 115 | DEBUGP("ipv6_esp: new pointer too large! \n"); | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | /* ESP header not found */ | ||
| 121 | if (temp != MASK_ESP) | ||
| 122 | return 0; | 59 | return 0; |
| 123 | 60 | ||
| 124 | if (len < sizeof(struct ip_esp_hdr)) { | 61 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); |
| 62 | if (eh == NULL) { | ||
| 125 | *hotdrop = 1; | 63 | *hotdrop = 1; |
| 126 | return 0; | 64 | return 0; |
| 127 | } | 65 | } |
| 128 | 66 | ||
| 129 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); | ||
| 130 | BUG_ON(eh == NULL); | ||
| 131 | |||
| 132 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); | 67 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); |
| 133 | 68 | ||
| 134 | return (eh != NULL) | 69 | return (eh != NULL) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 4bfa30a9bc80..085d5f8eea29 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
| @@ -48,90 +48,18 @@ match(const struct sk_buff *skb, | |||
| 48 | unsigned int protoff, | 48 | unsigned int protoff, |
| 49 | int *hotdrop) | 49 | int *hotdrop) |
| 50 | { | 50 | { |
| 51 | struct frag_hdr _frag, *fh = NULL; | 51 | struct frag_hdr _frag, *fh; |
| 52 | const struct ip6t_frag *fraginfo = matchinfo; | 52 | const struct ip6t_frag *fraginfo = matchinfo; |
| 53 | unsigned int temp; | ||
| 54 | int len; | ||
| 55 | u8 nexthdr; | ||
| 56 | unsigned int ptr; | 53 | unsigned int ptr; |
| 57 | unsigned int hdrlen = 0; | ||
| 58 | |||
| 59 | /* type of the 1st exthdr */ | ||
| 60 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 61 | /* pointer to the 1st exthdr */ | ||
| 62 | ptr = sizeof(struct ipv6hdr); | ||
| 63 | /* available length */ | ||
| 64 | len = skb->len - ptr; | ||
| 65 | temp = 0; | ||
| 66 | |||
| 67 | while (ip6t_ext_hdr(nexthdr)) { | ||
| 68 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 69 | |||
| 70 | DEBUGP("ipv6_frag header iteration \n"); | ||
| 71 | |||
| 72 | /* Is there enough space for the next ext header? */ | ||
| 73 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
| 74 | return 0; | ||
| 75 | /* No more exthdr -> evaluate */ | ||
| 76 | if (nexthdr == NEXTHDR_NONE) { | ||
| 77 | break; | ||
| 78 | } | ||
| 79 | /* ESP -> evaluate */ | ||
| 80 | if (nexthdr == NEXTHDR_ESP) { | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | |||
| 84 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 85 | BUG_ON(hp == NULL); | ||
| 86 | |||
| 87 | /* Calculate the header length */ | ||
| 88 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 89 | hdrlen = 8; | ||
| 90 | } else if (nexthdr == NEXTHDR_AUTH) | ||
| 91 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 92 | else | ||
| 93 | hdrlen = ipv6_optlen(hp); | ||
| 94 | |||
| 95 | /* FRAG -> evaluate */ | ||
| 96 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 97 | temp |= MASK_FRAGMENT; | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | /* set the flag */ | ||
| 103 | switch (nexthdr){ | ||
| 104 | case NEXTHDR_HOP: | ||
| 105 | case NEXTHDR_ROUTING: | ||
| 106 | case NEXTHDR_FRAGMENT: | ||
| 107 | case NEXTHDR_AUTH: | ||
| 108 | case NEXTHDR_DEST: | ||
| 109 | break; | ||
| 110 | default: | ||
| 111 | DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr); | ||
| 112 | return 0; | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | |||
| 116 | nexthdr = hp->nexthdr; | ||
| 117 | len -= hdrlen; | ||
| 118 | ptr += hdrlen; | ||
| 119 | if ( ptr > skb->len ) { | ||
| 120 | DEBUGP("ipv6_frag: new pointer too large! \n"); | ||
| 121 | break; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | /* FRAG header not found */ | ||
| 126 | if ( temp != MASK_FRAGMENT ) return 0; | ||
| 127 | |||
| 128 | if (len < sizeof(struct frag_hdr)){ | ||
| 129 | *hotdrop = 1; | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | 54 | ||
| 133 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 55 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0) |
| 134 | BUG_ON(fh == NULL); | 56 | return 0; |
| 57 | |||
| 58 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | ||
| 59 | if (fh == NULL){ | ||
| 60 | *hotdrop = 1; | ||
| 61 | return 0; | ||
| 62 | } | ||
| 135 | 63 | ||
| 136 | DEBUGP("INFO %04X ", fh->frag_off); | 64 | DEBUGP("INFO %04X ", fh->frag_off); |
| 137 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); | 65 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 27f3650d127e..1d09485111d0 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
| @@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
| 63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
| 64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
| 65 | unsigned int temp; | 65 | unsigned int temp; |
| 66 | unsigned int len; | ||
| 67 | u8 nexthdr; | ||
| 68 | unsigned int ptr; | 66 | unsigned int ptr; |
| 69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
| 70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
| @@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
| 72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
| 73 | unsigned int optlen; | 71 | unsigned int optlen; |
| 74 | 72 | ||
| 75 | /* type of the 1st exthdr */ | ||
| 76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
| 77 | /* pointer to the 1st exthdr */ | ||
| 78 | ptr = sizeof(struct ipv6hdr); | ||
| 79 | /* available length */ | ||
| 80 | len = skb->len - ptr; | ||
| 81 | temp = 0; | ||
| 82 | |||
| 83 | while (ip6t_ext_hdr(nexthdr)) { | ||
| 84 | struct ipv6_opt_hdr _hdr, *hp; | ||
| 85 | |||
| 86 | DEBUGP("ipv6_opts header iteration \n"); | ||
| 87 | |||
| 88 | /* Is there enough space for the next ext header? */ | ||
| 89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
| 90 | return 0; | ||
| 91 | /* No more exthdr -> evaluate */ | ||
| 92 | if (nexthdr == NEXTHDR_NONE) { | ||
| 93 | break; | ||
| 94 | } | ||
| 95 | /* ESP -> evaluate */ | ||
| 96 | if (nexthdr == NEXTHDR_ESP) { | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | |||
| 100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 101 | BUG_ON(hp == NULL); | ||
| 102 | |||
| 103 | /* Calculate the header length */ | ||
| 104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 105 | hdrlen = 8; | ||
| 106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
| 107 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 108 | else | ||
| 109 | hdrlen = ipv6_optlen(hp); | ||
| 110 | |||
| 111 | /* OPTS -> evaluate */ | ||
| 112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
| 113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
| 114 | temp |= MASK_HOPOPTS; | ||
| 115 | #else | 75 | #else |
| 116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
| 117 | temp |= MASK_DSTOPTS; | ||
| 118 | #endif | 77 | #endif |
| 119 | break; | 78 | return 0; |
| 120 | } | ||
| 121 | |||
| 122 | 79 | ||
| 123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
| 124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
| 125 | case NEXTHDR_HOP: | ||
| 126 | case NEXTHDR_ROUTING: | ||
| 127 | case NEXTHDR_FRAGMENT: | ||
| 128 | case NEXTHDR_AUTH: | ||
| 129 | case NEXTHDR_DEST: | ||
| 130 | break; | ||
| 131 | default: | ||
| 132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
| 133 | return 0; | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | |||
| 137 | nexthdr = hp->nexthdr; | ||
| 138 | len -= hdrlen; | ||
| 139 | ptr += hdrlen; | ||
| 140 | if ( ptr > skb->len ) { | ||
| 141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
| 142 | break; | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | /* OPTIONS header not found */ | ||
| 147 | #if HOPBYHOP | ||
| 148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
| 149 | #else | ||
| 150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
| 151 | #endif | ||
| 152 | |||
| 153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
| 154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
| 155 | return 0; | 83 | return 0; |
| 156 | } | 84 | } |
| 157 | 85 | ||
| 158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
| 87 | if (skb->len - ptr < hdrlen){ | ||
| 159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
| 160 | return 0; | 89 | return 0; |
| 161 | } | 90 | } |
| 162 | 91 | ||
| 163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
| 164 | BUG_ON(oh == NULL); | ||
| 165 | |||
| 166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
| 167 | 93 | ||
| 168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 2bb670037df3..beb2fd5cebbb 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
| @@ -50,98 +50,29 @@ match(const struct sk_buff *skb, | |||
| 50 | unsigned int protoff, | 50 | unsigned int protoff, |
| 51 | int *hotdrop) | 51 | int *hotdrop) |
| 52 | { | 52 | { |
| 53 | struct ipv6_rt_hdr _route, *rh = NULL; | 53 | struct ipv6_rt_hdr _route, *rh; |
| 54 | const struct ip6t_rt *rtinfo = matchinfo; | 54 | const struct ip6t_rt *rtinfo = matchinfo; |
| 55 | unsigned int temp; | 55 | unsigned int temp; |
| 56 | unsigned int len; | ||
| 57 | u8 nexthdr; | ||
| 58 | unsigned int ptr; | 56 | unsigned int ptr; |
| 59 | unsigned int hdrlen = 0; | 57 | unsigned int hdrlen = 0; |
| 60 | unsigned int ret = 0; | 58 | unsigned int ret = 0; |
| 61 | struct in6_addr *ap, _addr; | 59 | struct in6_addr *ap, _addr; |
| 62 | 60 | ||
| 63 | /* type of the 1st exthdr */ | 61 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0) |
| 64 | nexthdr = skb->nh.ipv6h->nexthdr; | 62 | return 0; |
| 65 | /* pointer to the 1st exthdr */ | ||
| 66 | ptr = sizeof(struct ipv6hdr); | ||
| 67 | /* available length */ | ||
| 68 | len = skb->len - ptr; | ||
| 69 | temp = 0; | ||
| 70 | 63 | ||
| 71 | while (ip6t_ext_hdr(nexthdr)) { | 64 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
| 72 | struct ipv6_opt_hdr _hdr, *hp; | 65 | if (rh == NULL){ |
| 73 | |||
| 74 | DEBUGP("ipv6_rt header iteration \n"); | ||
| 75 | |||
| 76 | /* Is there enough space for the next ext header? */ | ||
| 77 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
| 78 | return 0; | ||
| 79 | /* No more exthdr -> evaluate */ | ||
| 80 | if (nexthdr == NEXTHDR_NONE) { | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | /* ESP -> evaluate */ | ||
| 84 | if (nexthdr == NEXTHDR_ESP) { | ||
| 85 | break; | ||
| 86 | } | ||
| 87 | |||
| 88 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
| 89 | BUG_ON(hp == NULL); | ||
| 90 | |||
| 91 | /* Calculate the header length */ | ||
| 92 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
| 93 | hdrlen = 8; | ||
| 94 | } else if (nexthdr == NEXTHDR_AUTH) | ||
| 95 | hdrlen = (hp->hdrlen+2)<<2; | ||
| 96 | else | ||
| 97 | hdrlen = ipv6_optlen(hp); | ||
| 98 | |||
| 99 | /* ROUTING -> evaluate */ | ||
| 100 | if (nexthdr == NEXTHDR_ROUTING) { | ||
| 101 | temp |= MASK_ROUTING; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | |||
| 105 | |||
| 106 | /* set the flag */ | ||
| 107 | switch (nexthdr){ | ||
| 108 | case NEXTHDR_HOP: | ||
| 109 | case NEXTHDR_ROUTING: | ||
| 110 | case NEXTHDR_FRAGMENT: | ||
| 111 | case NEXTHDR_AUTH: | ||
| 112 | case NEXTHDR_DEST: | ||
| 113 | break; | ||
| 114 | default: | ||
| 115 | DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr); | ||
| 116 | return 0; | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | |||
| 120 | nexthdr = hp->nexthdr; | ||
| 121 | len -= hdrlen; | ||
| 122 | ptr += hdrlen; | ||
| 123 | if ( ptr > skb->len ) { | ||
| 124 | DEBUGP("ipv6_rt: new pointer is too large! \n"); | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | /* ROUTING header not found */ | ||
| 130 | if ( temp != MASK_ROUTING ) return 0; | ||
| 131 | |||
| 132 | if (len < (int)sizeof(struct ipv6_rt_hdr)){ | ||
| 133 | *hotdrop = 1; | 66 | *hotdrop = 1; |
| 134 | return 0; | 67 | return 0; |
| 135 | } | 68 | } |
| 136 | 69 | ||
| 137 | if (len < hdrlen){ | 70 | hdrlen = ipv6_optlen(rh); |
| 71 | if (skb->len - ptr < hdrlen){ | ||
| 138 | /* Pcket smaller than its length field */ | 72 | /* Pcket smaller than its length field */ |
| 139 | return 0; | 73 | return 0; |
| 140 | } | 74 | } |
| 141 | 75 | ||
| 142 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | ||
| 143 | BUG_ON(rh == NULL); | ||
| 144 | |||
| 145 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); | 76 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); |
| 146 | DEBUGP("TYPE %04X ", rh->type); | 77 | DEBUGP("TYPE %04X ", rh->type); |
| 147 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); | 78 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5aa3691c578d..a1265a320b11 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
| 627 | 627 | ||
| 628 | if (type && code) { | 628 | if (type && code) { |
| 629 | get_user(fl->fl_icmp_type, type); | 629 | get_user(fl->fl_icmp_type, type); |
| 630 | __get_user(fl->fl_icmp_code, code); | 630 | get_user(fl->fl_icmp_code, code); |
| 631 | probed = 1; | 631 | probed = 1; |
| 632 | } | 632 | } |
| 633 | break; | 633 | break; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 80643e6b346b..d693cb988b78 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -209,9 +209,11 @@ static __inline__ void __tcp_v6_hash(struct sock *sk) | |||
| 209 | lock = &tcp_hashinfo.lhash_lock; | 209 | lock = &tcp_hashinfo.lhash_lock; |
| 210 | inet_listen_wlock(&tcp_hashinfo); | 210 | inet_listen_wlock(&tcp_hashinfo); |
| 211 | } else { | 211 | } else { |
| 212 | sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size); | 212 | unsigned int hash; |
| 213 | list = &tcp_hashinfo.ehash[sk->sk_hashent].chain; | 213 | sk->sk_hash = hash = inet6_sk_ehashfn(sk); |
| 214 | lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock; | 214 | hash &= (tcp_hashinfo.ehash_size - 1); |
| 215 | list = &tcp_hashinfo.ehash[hash].chain; | ||
| 216 | lock = &tcp_hashinfo.ehash[hash].lock; | ||
| 215 | write_lock(lock); | 217 | write_lock(lock); |
| 216 | } | 218 | } |
| 217 | 219 | ||
| @@ -322,13 +324,13 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, | |||
| 322 | const struct in6_addr *saddr = &np->daddr; | 324 | const struct in6_addr *saddr = &np->daddr; |
| 323 | const int dif = sk->sk_bound_dev_if; | 325 | const int dif = sk->sk_bound_dev_if; |
| 324 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); | 326 | const u32 ports = INET_COMBINED_PORTS(inet->dport, lport); |
| 325 | const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport, | 327 | unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport); |
| 326 | tcp_hashinfo.ehash_size); | 328 | struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash); |
| 327 | struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash]; | ||
| 328 | struct sock *sk2; | 329 | struct sock *sk2; |
| 329 | const struct hlist_node *node; | 330 | const struct hlist_node *node; |
| 330 | struct inet_timewait_sock *tw; | 331 | struct inet_timewait_sock *tw; |
| 331 | 332 | ||
| 333 | prefetch(head->chain.first); | ||
| 332 | write_lock(&head->lock); | 334 | write_lock(&head->lock); |
| 333 | 335 | ||
| 334 | /* Check TIME-WAIT sockets first. */ | 336 | /* Check TIME-WAIT sockets first. */ |
| @@ -365,14 +367,14 @@ static int __tcp_v6_check_established(struct sock *sk, const __u16 lport, | |||
| 365 | 367 | ||
| 366 | /* And established part... */ | 368 | /* And established part... */ |
| 367 | sk_for_each(sk2, node, &head->chain) { | 369 | sk_for_each(sk2, node, &head->chain) { |
| 368 | if (INET6_MATCH(sk2, saddr, daddr, ports, dif)) | 370 | if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif)) |
| 369 | goto not_unique; | 371 | goto not_unique; |
| 370 | } | 372 | } |
| 371 | 373 | ||
| 372 | unique: | 374 | unique: |
| 373 | BUG_TRAP(sk_unhashed(sk)); | 375 | BUG_TRAP(sk_unhashed(sk)); |
| 374 | __sk_add_node(sk, &head->chain); | 376 | __sk_add_node(sk, &head->chain); |
| 375 | sk->sk_hashent = hash; | 377 | sk->sk_hash = hash; |
| 376 | sock_prot_inc_use(sk->sk_prot); | 378 | sock_prot_inc_use(sk->sk_prot); |
| 377 | write_unlock(&head->lock); | 379 | write_unlock(&head->lock); |
| 378 | 380 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69b146843a20..e4cad11f284a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -405,9 +405,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
| 405 | continue; | 405 | continue; |
| 406 | 406 | ||
| 407 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 407 | if (!ipv6_addr_any(&np->rcv_saddr)) { |
| 408 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 408 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
| 409 | return s; | 409 | continue; |
| 410 | continue; | ||
| 411 | } | 410 | } |
| 412 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) | 411 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) |
| 413 | continue; | 412 | continue; |
| @@ -640,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 640 | int tclass = -1; | 639 | int tclass = -1; |
| 641 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 640 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
| 642 | int err; | 641 | int err; |
| 642 | int connected = 0; | ||
| 643 | 643 | ||
| 644 | /* destination address check */ | 644 | /* destination address check */ |
| 645 | if (sin6) { | 645 | if (sin6) { |
| @@ -749,6 +749,7 @@ do_udp_sendmsg: | |||
| 749 | fl->fl_ip_dport = inet->dport; | 749 | fl->fl_ip_dport = inet->dport; |
| 750 | daddr = &np->daddr; | 750 | daddr = &np->daddr; |
| 751 | fl->fl6_flowlabel = np->flow_label; | 751 | fl->fl6_flowlabel = np->flow_label; |
| 752 | connected = 1; | ||
| 752 | } | 753 | } |
| 753 | 754 | ||
| 754 | if (!fl->oif) | 755 | if (!fl->oif) |
| @@ -771,6 +772,7 @@ do_udp_sendmsg: | |||
| 771 | } | 772 | } |
| 772 | if (!(opt->opt_nflen|opt->opt_flen)) | 773 | if (!(opt->opt_nflen|opt->opt_flen)) |
| 773 | opt = NULL; | 774 | opt = NULL; |
| 775 | connected = 0; | ||
| 774 | } | 776 | } |
| 775 | if (opt == NULL) | 777 | if (opt == NULL) |
| 776 | opt = np->opt; | 778 | opt = np->opt; |
| @@ -788,10 +790,13 @@ do_udp_sendmsg: | |||
| 788 | ipv6_addr_copy(&final, &fl->fl6_dst); | 790 | ipv6_addr_copy(&final, &fl->fl6_dst); |
| 789 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 791 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); |
| 790 | final_p = &final; | 792 | final_p = &final; |
| 793 | connected = 0; | ||
| 791 | } | 794 | } |
| 792 | 795 | ||
| 793 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) | 796 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { |
| 794 | fl->oif = np->mcast_oif; | 797 | fl->oif = np->mcast_oif; |
| 798 | connected = 0; | ||
| 799 | } | ||
| 795 | 800 | ||
| 796 | err = ip6_dst_lookup(sk, &dst, fl); | 801 | err = ip6_dst_lookup(sk, &dst, fl); |
| 797 | if (err) | 802 | if (err) |
| @@ -847,10 +852,16 @@ do_append_data: | |||
| 847 | else if (!corkreq) | 852 | else if (!corkreq) |
| 848 | err = udp_v6_push_pending_frames(sk, up); | 853 | err = udp_v6_push_pending_frames(sk, up); |
| 849 | 854 | ||
| 850 | if (dst) | 855 | if (dst) { |
| 851 | ip6_dst_store(sk, dst, | 856 | if (connected) { |
| 852 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 857 | ip6_dst_store(sk, dst, |
| 853 | &np->daddr : NULL); | 858 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? |
| 859 | &np->daddr : NULL); | ||
| 860 | } else { | ||
| 861 | dst_release(dst); | ||
| 862 | } | ||
| 863 | } | ||
| 864 | |||
| 854 | if (err > 0) | 865 | if (err > 0) |
| 855 | err = np->recverr ? net_xmit_errno(err) : 0; | 866 | err = np->recverr ? net_xmit_errno(err) : 0; |
| 856 | release_sock(sk); | 867 | release_sock(sk); |
