From c5027c9a896fbe05367fb893a274deca5114bfd0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 5 Apr 2007 15:54:02 -0700 Subject: [XFRM]: beet: fix IP option encapsulation Beet mode calculates an incorrect value for the transport header location when IP options are present, resulting in encapsulation errors. The correct location is 4 or 8 bytes before the end of the original IP header, depending on whether the pseudo header is padded. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/xfrm4_mode_beet.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 89cf59ea7bbe..16efc66a7c3f 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/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; -- cgit v1.2.3-59-g8ed1b From 04fef9893a1fa5d429522e09bc9591736408f2e8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 5 Apr 2007 15:54:39 -0700 Subject: [XFRM]: beet: use IPOPT_NOP for option padding draft-nikander-esp-beet-mode-07.txt states "The padding MUST be filled with NOP options as defined in Internet Protocol [1] section 3.1 Internet header format.", so do that. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/xfrm4_mode_beet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 16efc66a7c3f..f8544b7f02de 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -54,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; -- cgit v1.2.3-59-g8ed1b From d4b1e840629562953d81c9fe0a3a67473f3d993c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 5 Apr 2007 15:59:41 -0700 Subject: [XFRM]: beet: fix beet mode decapsulation Beet mode decapsulation fails to properly set up the skb pointers, which only works by accident in combination with CONFIG_NETFILTER, since in that case the skb is fixed up in xfrm4_input before passing it to the netfilter hooks. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/xfrm4_mode_beet.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index f8544b7f02de..b94775a86863 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -83,24 +83,24 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*ph))) goto out; - 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; 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); 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) -- cgit v1.2.3-59-g8ed1b From 254d0d24e31c3df64ccfff349c9aa9d1e5989819 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Thu, 5 Apr 2007 16:03:33 -0700 Subject: [XFRM]: beet: fix IP option decapsulation Beet mode looks for the beet pseudo header after the outer IP header, which is wrong since that is followed by the ESP header. Additionally it needs to adjust the packet length after removing the pseudo header and point the data pointer to the real data location. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/xfrm4_mode_beet.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index b94775a86863..f68dfd8a0f5c 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c @@ -78,10 +78,11 @@ 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 = sizeof(*ph) + ph->padlen; optlen = ph->hdrlen * 8 - phlen; @@ -90,6 +91,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) if (!pskb_may_pull(skb, phlen + optlen)) goto out; + skb->len -= phlen + optlen; ph_nexthdr = ph->nexthdr; } @@ -97,6 +99,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) 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; -- cgit v1.2.3-59-g8ed1b From 161980f4c6b846625efe6227420175cb41477de3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 6 Apr 2007 11:42:27 -0700 Subject: [IPV6]: Revert recent change to rt6_check_dev(). This reverts a0d78ebf3a0e33a1aeacf2fc518ad9273d6a1c2f It causes pings to link-local addresses to fail. Signed-off-by: David S. Miller --- net/ipv6/route.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3931b33b25e8..ad9b285692ba 100644 --- a/net/ipv6/route.c +++ b/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) -- cgit v1.2.3-59-g8ed1b From b8fa2f3a82069304acac1f9e957d491585f4f49a Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 6 Apr 2007 17:35:37 -0700 Subject: [TG3]: Fix crash during tg3_init_one(). The driver will crash when the chip has been initialized by EFI before tg3_init_one(). In this case, the driver will call tg3_chip_reset() before allocating consistent memory. The bug is fixed by checking for tp->hw_status before accessing it during tg3_chip_reset(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0acee9f324e9..256969e1300c 100644 --- a/drivers/net/tg3.c +++ b/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); -- cgit v1.2.3-59-g8ed1b