aboutsummaryrefslogtreecommitdiff
path: root/net/ipv6
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-05-03 13:30:35 +0100
committerDavid Woodhouse <dwmw2@infradead.org>2006-05-03 13:30:35 +0100
commitedc4ff7c08e9885c40e60c4fb39fa42cc91a0602 (patch)
treef375d28043dd4457428a841167dc93d760ba9a46 /net/ipv6
parentcbb9a56177b16294ed347ba7fcb1c66c8adb5dc4 (diff)
parente17df688f7064dae1417ce425dd1e4b71d24d63b (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/exthdrs.c16
-rw-r--r--net/ipv6/ip6_input.c3
-rw-r--r--net/ipv6/netfilter/ip6_tables.c13
-rw-r--r--net/ipv6/route.c5
-rw-r--r--net/ipv6/xfrm6_policy.c8
5 files changed, 24 insertions, 21 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 2a1e7e45b89..a18d4256372 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
{ -1, }
};
-int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
+int ipv6_parse_hopopts(struct sk_buff *skb)
{
struct inet6_skb_parm *opt = IP6CB(skb);
+ /*
+ * skb->nh.raw is equal to skb->data, and
+ * skb->h.raw - skb->nh.raw is always equal to
+ * sizeof(struct ipv6hdr) by definition of
+ * hop-by-hop options.
+ */
+ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
+ !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
+ kfree_skb(skb);
+ return -1;
+ }
+
opt->hop = sizeof(struct ipv6hdr);
if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
skb->h.raw += (skb->h.raw[1]+1)<<3;
opt->nhoff = sizeof(struct ipv6hdr);
- return sizeof(struct ipv6hdr);
+ return 1;
}
return -1;
}
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 29f73592e68..aceee252503 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
}
if (hdr->nexthdr == NEXTHDR_HOP) {
- if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
+ if (ipv6_parse_hopopts(skb) < 0) {
IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
return 0;
}
- hdr = skb->nh.ipv6h;
}
return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 642b4b11464..0a673038344 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -288,19 +288,6 @@ ip6t_do_table(struct sk_buff **pskb,
table_base = (void *)private->entries[smp_processor_id()];
e = get_entry(table_base, private->hook_entry[hook]);
-#ifdef CONFIG_NETFILTER_DEBUG
- /* Check noone else using our table */
- if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
- && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
- printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
- smp_processor_id(),
- table->name,
- &((struct ip6t_entry *)table_base)->comefrom,
- ((struct ip6t_entry *)table_base)->comefrom);
- }
- ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
-#endif
-
/* For return from builtin chain */
back = get_entry(table_base, private->underflow[hook]);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 79078747a64..0190e39096b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -317,7 +317,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
__FUNCTION__, head, head ? *head : NULL, oif);
for (rt = rt0, metric = rt0->rt6i_metric;
- rt && rt->rt6i_metric == metric;
+ rt && rt->rt6i_metric == metric && (!last || rt != rt0);
rt = rt->u.next) {
int m;
@@ -343,9 +343,12 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif,
(strict & RT6_SELECT_F_REACHABLE) &&
last && last != rt0) {
/* no entries matched; do round-robin */
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+ spin_lock(&lock);
*head = rt0->u.next;
rt0->u.next = last->u.next;
last->u.next = rt0;
+ spin_unlock(&lock);
}
RT6_TRACE("%s() => %p, score=%d\n",
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 91cce8b2d7a..88c840f1beb 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -191,16 +191,18 @@ error:
static inline void
_decode_session6(struct sk_buff *skb, struct flowi *fl)
{
- u16 offset = sizeof(struct ipv6hdr);
+ u16 offset = skb->h.raw - skb->nh.raw;
struct ipv6hdr *hdr = skb->nh.ipv6h;
- struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
+ struct ipv6_opt_hdr *exthdr;
+ u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
memset(fl, 0, sizeof(struct flowi));
ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+ exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+
switch (nexthdr) {
case NEXTHDR_ROUTING:
case NEXTHDR_HOP: