diff options
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 4 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 18 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 2 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 4 | ||||
-rw-r--r-- | net/ipv6/ndisc.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 | 69 | ||||
-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 | 31 |
18 files changed, 166 insertions, 504 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/esp6.c b/net/ipv6/esp6.c index 9b27460f0cc7..40d9a1935ab5 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <net/esp.h> | 31 | #include <net/esp.h> |
32 | #include <asm/scatterlist.h> | 32 | #include <asm/scatterlist.h> |
33 | #include <linux/crypto.h> | 33 | #include <linux/crypto.h> |
34 | #include <linux/kernel.h> | ||
34 | #include <linux/pfkeyv2.h> | 35 | #include <linux/pfkeyv2.h> |
35 | #include <linux/random.h> | 36 | #include <linux/random.h> |
36 | #include <net/icmp.h> | 37 | #include <net/icmp.h> |
@@ -66,10 +67,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
66 | 67 | ||
67 | alen = esp->auth.icv_trunc_len; | 68 | alen = esp->auth.icv_trunc_len; |
68 | tfm = esp->conf.tfm; | 69 | tfm = esp->conf.tfm; |
69 | blksize = (crypto_tfm_alg_blocksize(tfm) + 3) & ~3; | 70 | blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); |
70 | clen = (clen + 2 + blksize-1)&~(blksize-1); | 71 | clen = ALIGN(clen + 2, blksize); |
71 | if (esp->conf.padlen) | 72 | if (esp->conf.padlen) |
72 | clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); | 73 | clen = ALIGN(clen, esp->conf.padlen); |
73 | 74 | ||
74 | if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) { | 75 | if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) { |
75 | goto error; | 76 | goto error; |
@@ -133,7 +134,7 @@ static int esp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, stru | |||
133 | struct ipv6_esp_hdr *esph; | 134 | struct ipv6_esp_hdr *esph; |
134 | struct esp_data *esp = x->data; | 135 | struct esp_data *esp = x->data; |
135 | struct sk_buff *trailer; | 136 | struct sk_buff *trailer; |
136 | int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); | 137 | int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); |
137 | int alen = esp->auth.icv_trunc_len; | 138 | int alen = esp->auth.icv_trunc_len; |
138 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; | 139 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; |
139 | 140 | ||
@@ -235,16 +236,17 @@ out_nofree: | |||
235 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) | 236 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) |
236 | { | 237 | { |
237 | struct esp_data *esp = x->data; | 238 | struct esp_data *esp = x->data; |
238 | u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); | 239 | u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); |
239 | 240 | ||
240 | if (x->props.mode) { | 241 | if (x->props.mode) { |
241 | mtu = (mtu + 2 + blksize-1)&~(blksize-1); | 242 | mtu = ALIGN(mtu + 2, blksize); |
242 | } else { | 243 | } else { |
243 | /* The worst case. */ | 244 | /* The worst case. */ |
244 | mtu += 2 + blksize; | 245 | u32 padsize = ((blksize - 1) & 7) + 1; |
246 | mtu = ALIGN(mtu + 2, padsize) + blksize - padsize; | ||
245 | } | 247 | } |
246 | if (esp->conf.padlen) | 248 | if (esp->conf.padlen) |
247 | mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1); | 249 | mtu = ALIGN(mtu, esp->conf.padlen); |
248 | 250 | ||
249 | return mtu + x->props.header_len + esp->auth.icv_full_len; | 251 | return mtu + x->props.header_len + esp->auth.icv_full_len; |
250 | } | 252 | } |
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..39a96c768102 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1393,7 +1393,7 @@ static void mld_sendpack(struct sk_buff *skb) | |||
1393 | 1393 | ||
1394 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) | 1394 | static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) |
1395 | { | 1395 | { |
1396 | return sizeof(struct mld2_grec) + 4*mld_scount(pmc,type,gdel,sdel); | 1396 | return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel); |
1397 | } | 1397 | } |
1398 | 1398 | ||
1399 | static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | 1399 | static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, |
@@ -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/ndisc.c b/net/ipv6/ndisc.c index 555a31347eda..305d9ee6d7db 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1450,7 +1450,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1450 | 1450 | ||
1451 | static void pndisc_redo(struct sk_buff *skb) | 1451 | static void pndisc_redo(struct sk_buff *skb) |
1452 | { | 1452 | { |
1453 | ndisc_rcv(skb); | 1453 | ndisc_recv_ns(skb); |
1454 | kfree_skb(skb); | 1454 | kfree_skb(skb); |
1455 | } | 1455 | } |
1456 | 1456 | ||
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..21deec25a12b 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
29 | #include <asm/semaphore.h> | 29 | #include <asm/semaphore.h> |
30 | #include <linux/proc_fs.h> | 30 | #include <linux/proc_fs.h> |
31 | #include <linux/cpumask.h> | ||
31 | 32 | ||
32 | #include <linux/netfilter_ipv6/ip6_tables.h> | 33 | #include <linux/netfilter_ipv6/ip6_tables.h> |
33 | 34 | ||
@@ -950,8 +951,10 @@ translate_table(const char *name, | |||
950 | } | 951 | } |
951 | 952 | ||
952 | /* And one copy for every other CPU */ | 953 | /* And one copy for every other CPU */ |
953 | for (i = 1; i < num_possible_cpus(); i++) { | 954 | for_each_cpu(i) { |
954 | memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i, | 955 | if (i == 0) |
956 | continue; | ||
957 | memcpy(newinfo->entries + SMP_ALIGN(newinfo->size) * i, | ||
955 | newinfo->entries, | 958 | newinfo->entries, |
956 | SMP_ALIGN(newinfo->size)); | 959 | SMP_ALIGN(newinfo->size)); |
957 | } | 960 | } |
@@ -972,7 +975,7 @@ replace_table(struct ip6t_table *table, | |||
972 | struct ip6t_entry *table_base; | 975 | struct ip6t_entry *table_base; |
973 | unsigned int i; | 976 | unsigned int i; |
974 | 977 | ||
975 | for (i = 0; i < num_possible_cpus(); i++) { | 978 | for_each_cpu(i) { |
976 | table_base = | 979 | table_base = |
977 | (void *)newinfo->entries | 980 | (void *)newinfo->entries |
978 | + TABLE_OFFSET(newinfo, i); | 981 | + TABLE_OFFSET(newinfo, i); |
@@ -1019,7 +1022,7 @@ get_counters(const struct ip6t_table_info *t, | |||
1019 | unsigned int cpu; | 1022 | unsigned int cpu; |
1020 | unsigned int i; | 1023 | unsigned int i; |
1021 | 1024 | ||
1022 | for (cpu = 0; cpu < num_possible_cpus(); cpu++) { | 1025 | for_each_cpu(cpu) { |
1023 | i = 0; | 1026 | i = 0; |
1024 | IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), | 1027 | IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu), |
1025 | t->size, | 1028 | t->size, |
@@ -1153,7 +1156,8 @@ do_replace(void __user *user, unsigned int len) | |||
1153 | return -ENOMEM; | 1156 | return -ENOMEM; |
1154 | 1157 | ||
1155 | newinfo = vmalloc(sizeof(struct ip6t_table_info) | 1158 | newinfo = vmalloc(sizeof(struct ip6t_table_info) |
1156 | + SMP_ALIGN(tmp.size) * num_possible_cpus()); | 1159 | + SMP_ALIGN(tmp.size) * |
1160 | (highest_possible_processor_id()+1)); | ||
1157 | if (!newinfo) | 1161 | if (!newinfo) |
1158 | return -ENOMEM; | 1162 | return -ENOMEM; |
1159 | 1163 | ||
@@ -1467,7 +1471,8 @@ int ip6t_register_table(struct ip6t_table *table, | |||
1467 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1471 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1468 | 1472 | ||
1469 | newinfo = vmalloc(sizeof(struct ip6t_table_info) | 1473 | newinfo = vmalloc(sizeof(struct ip6t_table_info) |
1470 | + SMP_ALIGN(repl->size) * num_possible_cpus()); | 1474 | + SMP_ALIGN(repl->size) * |
1475 | (highest_possible_processor_id()+1)); | ||
1471 | if (!newinfo) | 1476 | if (!newinfo) |
1472 | return -ENOMEM; | 1477 | return -ENOMEM; |
1473 | 1478 | ||
@@ -1955,6 +1960,57 @@ static void __exit fini(void) | |||
1955 | #endif | 1960 | #endif |
1956 | } | 1961 | } |
1957 | 1962 | ||
1963 | /* | ||
1964 | * find specified header up to transport protocol header. | ||
1965 | * If found target header, the offset to the header is set to *offset | ||
1966 | * and return 0. otherwise, return -1. | ||
1967 | * | ||
1968 | * Notes: - non-1st Fragment Header isn't skipped. | ||
1969 | * - ESP header isn't skipped. | ||
1970 | * - The target header may be trancated. | ||
1971 | */ | ||
1972 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) | ||
1973 | { | ||
1974 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | ||
1975 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
1976 | unsigned int len = skb->len - start; | ||
1977 | |||
1978 | while (nexthdr != target) { | ||
1979 | struct ipv6_opt_hdr _hdr, *hp; | ||
1980 | unsigned int hdrlen; | ||
1981 | |||
1982 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) | ||
1983 | return -1; | ||
1984 | hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); | ||
1985 | if (hp == NULL) | ||
1986 | return -1; | ||
1987 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
1988 | unsigned short _frag_off, *fp; | ||
1989 | fp = skb_header_pointer(skb, | ||
1990 | start+offsetof(struct frag_hdr, | ||
1991 | frag_off), | ||
1992 | sizeof(_frag_off), | ||
1993 | &_frag_off); | ||
1994 | if (fp == NULL) | ||
1995 | return -1; | ||
1996 | |||
1997 | if (ntohs(*fp) & ~0x7) | ||
1998 | return -1; | ||
1999 | hdrlen = 8; | ||
2000 | } else if (nexthdr == NEXTHDR_AUTH) | ||
2001 | hdrlen = (hp->hdrlen + 2) << 2; | ||
2002 | else | ||
2003 | hdrlen = ipv6_optlen(hp); | ||
2004 | |||
2005 | nexthdr = hp->nexthdr; | ||
2006 | len -= hdrlen; | ||
2007 | start += hdrlen; | ||
2008 | } | ||
2009 | |||
2010 | *offset = start; | ||
2011 | return 0; | ||
2012 | } | ||
2013 | |||
1958 | EXPORT_SYMBOL(ip6t_register_table); | 2014 | EXPORT_SYMBOL(ip6t_register_table); |
1959 | EXPORT_SYMBOL(ip6t_unregister_table); | 2015 | EXPORT_SYMBOL(ip6t_unregister_table); |
1960 | EXPORT_SYMBOL(ip6t_do_table); | 2016 | EXPORT_SYMBOL(ip6t_do_table); |
@@ -1963,6 +2019,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); | |||
1963 | EXPORT_SYMBOL(ip6t_register_target); | 2019 | EXPORT_SYMBOL(ip6t_register_target); |
1964 | EXPORT_SYMBOL(ip6t_unregister_target); | 2020 | EXPORT_SYMBOL(ip6t_unregister_target); |
1965 | EXPORT_SYMBOL(ip6t_ext_hdr); | 2021 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2022 | EXPORT_SYMBOL(ipv6_find_hdr); | ||
1966 | 2023 | ||
1967 | module_init(init); | 2024 | module_init(init); |
1968 | module_exit(fini); | 2025 | 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..bf9519341fd3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -99,7 +99,7 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
99 | next:; | 99 | next:; |
100 | } | 100 | } |
101 | result = best; | 101 | result = best; |
102 | for(;; result += UDP_HTABLE_SIZE) { | 102 | for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { |
103 | if (result > sysctl_local_port_range[1]) | 103 | if (result > sysctl_local_port_range[1]) |
104 | result = sysctl_local_port_range[0] | 104 | result = sysctl_local_port_range[0] |
105 | + ((result - sysctl_local_port_range[0]) & | 105 | + ((result - sysctl_local_port_range[0]) & |
@@ -107,6 +107,8 @@ static int udp_v6_get_port(struct sock *sk, unsigned short snum) | |||
107 | if (!udp_lport_inuse(result)) | 107 | if (!udp_lport_inuse(result)) |
108 | break; | 108 | break; |
109 | } | 109 | } |
110 | if (i >= (1 << 16) / UDP_HTABLE_SIZE) | ||
111 | goto fail; | ||
110 | gotit: | 112 | gotit: |
111 | udp_port_rover = snum = result; | 113 | udp_port_rover = snum = result; |
112 | } else { | 114 | } else { |
@@ -405,9 +407,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
405 | continue; | 407 | continue; |
406 | 408 | ||
407 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 409 | if (!ipv6_addr_any(&np->rcv_saddr)) { |
408 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 410 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
409 | return s; | 411 | continue; |
410 | continue; | ||
411 | } | 412 | } |
412 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) | 413 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) |
413 | continue; | 414 | continue; |
@@ -640,6 +641,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
640 | int tclass = -1; | 641 | int tclass = -1; |
641 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 642 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
642 | int err; | 643 | int err; |
644 | int connected = 0; | ||
643 | 645 | ||
644 | /* destination address check */ | 646 | /* destination address check */ |
645 | if (sin6) { | 647 | if (sin6) { |
@@ -749,6 +751,7 @@ do_udp_sendmsg: | |||
749 | fl->fl_ip_dport = inet->dport; | 751 | fl->fl_ip_dport = inet->dport; |
750 | daddr = &np->daddr; | 752 | daddr = &np->daddr; |
751 | fl->fl6_flowlabel = np->flow_label; | 753 | fl->fl6_flowlabel = np->flow_label; |
754 | connected = 1; | ||
752 | } | 755 | } |
753 | 756 | ||
754 | if (!fl->oif) | 757 | if (!fl->oif) |
@@ -771,6 +774,7 @@ do_udp_sendmsg: | |||
771 | } | 774 | } |
772 | if (!(opt->opt_nflen|opt->opt_flen)) | 775 | if (!(opt->opt_nflen|opt->opt_flen)) |
773 | opt = NULL; | 776 | opt = NULL; |
777 | connected = 0; | ||
774 | } | 778 | } |
775 | if (opt == NULL) | 779 | if (opt == NULL) |
776 | opt = np->opt; | 780 | opt = np->opt; |
@@ -788,10 +792,13 @@ do_udp_sendmsg: | |||
788 | ipv6_addr_copy(&final, &fl->fl6_dst); | 792 | ipv6_addr_copy(&final, &fl->fl6_dst); |
789 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 793 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); |
790 | final_p = &final; | 794 | final_p = &final; |
795 | connected = 0; | ||
791 | } | 796 | } |
792 | 797 | ||
793 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) | 798 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { |
794 | fl->oif = np->mcast_oif; | 799 | fl->oif = np->mcast_oif; |
800 | connected = 0; | ||
801 | } | ||
795 | 802 | ||
796 | err = ip6_dst_lookup(sk, &dst, fl); | 803 | err = ip6_dst_lookup(sk, &dst, fl); |
797 | if (err) | 804 | if (err) |
@@ -847,10 +854,16 @@ do_append_data: | |||
847 | else if (!corkreq) | 854 | else if (!corkreq) |
848 | err = udp_v6_push_pending_frames(sk, up); | 855 | err = udp_v6_push_pending_frames(sk, up); |
849 | 856 | ||
850 | if (dst) | 857 | if (dst) { |
851 | ip6_dst_store(sk, dst, | 858 | if (connected) { |
852 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 859 | ip6_dst_store(sk, dst, |
853 | &np->daddr : NULL); | 860 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? |
861 | &np->daddr : NULL); | ||
862 | } else { | ||
863 | dst_release(dst); | ||
864 | } | ||
865 | } | ||
866 | |||
854 | if (err > 0) | 867 | if (err > 0) |
855 | err = np->recverr ? net_xmit_errno(err) : 0; | 868 | err = np->recverr ? net_xmit_errno(err) : 0; |
856 | release_sock(sk); | 869 | release_sock(sk); |