Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [TG3]: Fix crash during tg3_init_one().
  [IPV6]: Revert recent change to rt6_check_dev().
  [XFRM]: beet: fix IP option decapsulation
  [XFRM]: beet: fix beet mode decapsulation
  [XFRM]: beet: use IPOPT_NOP for option padding
  [XFRM]: beet: fix IP option encapsulation
Linus Torvalds 18 years ago
parent
commit
bbef618190
3 changed files with 24 additions and 27 deletions
  1. 4 2
      drivers/net/tg3.c
  2. 15 11
      net/ipv4/xfrm4_mode_beet.c
  3. 5 14
      net/ipv6/route.c

+ 4 - 2
drivers/net/tg3.c

@@ -4834,8 +4834,10 @@ static int tg3_chip_reset(struct tg3 *tp)
 	 * sharing or irqpoll.
 	 */
 	tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
-	tp->hw_status->status = 0;
-	tp->hw_status->status_tag = 0;
+	if (tp->hw_status) {
+		tp->hw_status->status = 0;
+		tp->hw_status->status_tag = 0;
+	}
 	tp->last_tag = 0;
 	smp_mb();
 	synchronize_irq(tp->pdev->irq);

+ 15 - 11
net/ipv4/xfrm4_mode_beet.c

@@ -42,10 +42,9 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 
 	skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
 	top_iph = skb->nh.iph;
-	hdrlen = iph->ihl * 4 - optlen;
-	skb->h.raw += hdrlen;
+	skb->h.raw += sizeof(*iph) - hdrlen;
 
-	memmove(top_iph, iph, hdrlen);
+	memmove(top_iph, iph, sizeof(*iph));
 	if (unlikely(optlen)) {
 		struct ip_beet_phdr *ph;
 
@@ -55,6 +54,8 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
 		ph->padlen = 4 - (optlen & 4);
 		ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
 		ph->nexthdr = top_iph->protocol;
+		if (ph->padlen)
+			memset(ph + 1, IPOPT_NOP, ph->padlen);
 
 		top_iph->protocol = IPPROTO_BEETPH;
 		top_iph->ihl = sizeof(struct iphdr) / 4;
@@ -77,29 +78,32 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 	protocol = iph->protocol;
 
 	if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
-		struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);
+		struct ip_beet_phdr *ph;
 
 		if (!pskb_may_pull(skb, sizeof(*ph)))
 			goto out;
+		ph = (struct ip_beet_phdr *)(skb->h.ipiph + 1);
 
-		phlen = ph->hdrlen * 8;
-		optlen = phlen - ph->padlen - sizeof(*ph);
+		phlen = sizeof(*ph) + ph->padlen;
+		optlen = ph->hdrlen * 8 - phlen;
 		if (optlen < 0 || optlen & 3 || optlen > 250)
 			goto out;
 
-		if (!pskb_may_pull(skb, phlen))
+		if (!pskb_may_pull(skb, phlen + optlen))
 			goto out;
+		skb->len -= phlen + optlen;
 
 		ph_nexthdr = ph->nexthdr;
 	}
 
-	skb_push(skb, sizeof(*iph) - phlen + optlen);
-	memmove(skb->data, skb->nh.raw, sizeof(*iph));
-	skb->nh.raw = skb->data;
+	skb->nh.raw = skb->data + (phlen - sizeof(*iph));
+	memmove(skb->nh.raw, iph, sizeof(*iph));
+	skb->h.raw = skb->data + (phlen + optlen);
+	skb->data = skb->h.raw;
 
 	iph = skb->nh.iph;
 	iph->ihl = (sizeof(*iph) + optlen) / 4;
-	iph->tot_len = htons(skb->len);
+	iph->tot_len = htons(skb->len + iph->ihl * 4);
 	iph->daddr = x->sel.daddr.a4;
 	iph->saddr = x->sel.saddr.a4;
 	if (ph_nexthdr)

+ 5 - 14
net/ipv6/route.c

@@ -311,21 +311,12 @@ static inline void rt6_probe(struct rt6_info *rt)
 static inline int rt6_check_dev(struct rt6_info *rt, int oif)
 {
 	struct net_device *dev = rt->rt6i_dev;
-	int ret = 0;
-
-	if (!oif)
-		return 2;
-	if (dev->flags & IFF_LOOPBACK) {
-		if (!WARN_ON(rt->rt6i_idev == NULL) &&
-		    rt->rt6i_idev->dev->ifindex == oif)
-			ret = 1;
-		else
-			return 0;
-	}
-	if (dev->ifindex == oif)
+	if (!oif || dev->ifindex == oif)
 		return 2;
-
-	return ret;
+	if ((dev->flags & IFF_LOOPBACK) &&
+	    rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
+		return 1;
+	return 0;
 }
 
 static inline int rt6_check_neigh(struct rt6_info *rt)