Commit 551a10c7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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:
  [IPSEC]: Fix the address family to refer encap_family
  [IPSEC]: changing API of xfrm6_tunnel_register
  [IPSEC]: make sit use the xfrm4_tunnel_register
  [IPSEC]: Changing API of xfrm4_tunnel_register.
  [TCP]: Prevent pseudo garbage in SYN's advertized window
  [NET_SCHED]: sch_hfsc: replace ASSERT macro by WARN_ON
  [BRIDGE] br_if: Fix oops in port_carrier_check
  [NETFILTER]: Clear GSO bits for TCP reset packet
  [TG3]: Update copyright, version, and reldate.
  [TG3]: Add some tx timeout debug messages.
  [TG3]: Use constant for PHY register 0x1e.
  [TG3]: Power down 5704 serdes transceiver when shutting down.
  [TG3]: 5906 doesn't need to switch to slower clock.
  [TG3]: 5722/5756 don't need PHY jitter workaround.
  [TG3]: Use lower DMA watermark for 5703.
  [TG3]: Save MSI state before suspend.
  [XFRM]: Fix IPv4 tunnel mode decapsulation with IPV6=n
  [IPV6] HASHTABLES: Use appropriate seed for caluculating ehash index.
parents f90203e0 928ba416
......@@ -4,7 +4,7 @@
* Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
* Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
* Copyright (C) 2004 Sun Microsystems Inc.
* Copyright (C) 2005 Broadcom Corporation.
* Copyright (C) 2005-2007 Broadcom Corporation.
*
* Firmware is:
* Derived from proprietary unpublished source code,
......@@ -64,8 +64,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.72"
#define DRV_MODULE_RELDATE "January 8, 2007"
#define DRV_MODULE_VERSION "3.73"
#define DRV_MODULE_RELDATE "February 12, 2007"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -1175,8 +1175,18 @@ static void tg3_nvram_unlock(struct tg3 *);
static void tg3_power_down_phy(struct tg3 *tp)
{
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
u32 serdes_cfg = tr32(MAC_SERDES_CFG);
sg_dig_ctrl |=
SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET;
tw32(SG_DIG_CTRL, sg_dig_ctrl);
tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15));
}
return;
}
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u32 val;
......@@ -1340,7 +1350,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
CLOCK_CTRL_PWRDOWN_PLL133, 40);
} else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
} else if ((tp->tg3_flags2 & TG3_FLG2_5780_CLASS) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)) {
/* do nothing */
} else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
......@@ -3724,13 +3735,23 @@ out:
tg3_full_unlock(tp);
}
static void tg3_dump_short_state(struct tg3 *tp)
{
printk(KERN_ERR PFX "DEBUG: MAC_TX_STATUS[%08x] MAC_RX_STATUS[%08x]\n",
tr32(MAC_TX_STATUS), tr32(MAC_RX_STATUS));
printk(KERN_ERR PFX "DEBUG: RDMAC_STATUS[%08x] WDMAC_STATUS[%08x]\n",
tr32(RDMAC_STATUS), tr32(WDMAC_STATUS));
}
static void tg3_tx_timeout(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
if (netif_msg_tx_err(tp))
if (netif_msg_tx_err(tp)) {
printk(KERN_ERR PFX "%s: transmit timed out, resetting\n",
dev->name);
tg3_dump_short_state(tp);
}
schedule_work(&tp->reset_task);
}
......@@ -6583,8 +6604,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
u32 tmp;
/* Clear CRC stats. */
if (!tg3_readphy(tp, 0x1e, &tmp)) {
tg3_writephy(tp, 0x1e, tmp | 0x8000);
if (!tg3_readphy(tp, MII_TG3_TEST1, &tmp)) {
tg3_writephy(tp, MII_TG3_TEST1,
tmp | MII_TG3_TEST1_CRC_EN);
tg3_readphy(tp, 0x14, &tmp);
}
}
......@@ -7408,8 +7430,9 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
u32 val;
spin_lock_bh(&tp->lock);
if (!tg3_readphy(tp, 0x1e, &val)) {
tg3_writephy(tp, 0x1e, val | 0x8000);
if (!tg3_readphy(tp, MII_TG3_TEST1, &val)) {
tg3_writephy(tp, MII_TG3_TEST1,
val | MII_TG3_TEST1_CRC_EN);
tg3_readphy(tp, 0x14, &val);
} else
val = 0;
......@@ -10779,7 +10802,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) {
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
if (tp->pdev->device != PCI_DEVICE_ID_TIGON3_5756 &&
tp->pdev->device != PCI_DEVICE_ID_TIGON3_5722)
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)
......@@ -11314,6 +11339,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
u32 ccval = (tr32(TG3PCI_CLOCK_CTRL) & 0x1f);
u32 read_water = 0x7;
/* If the 5704 is behind the EPB bridge, we can
* do the less restrictive ONE_DMA workaround for
......@@ -11325,8 +11351,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
else if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703)
read_water = 4;
/* Set bit 23 to enable PCIX hw bug fix */
tp->dma_rwctrl |= 0x009f0000;
tp->dma_rwctrl |=
(read_water << DMA_RWCTRL_READ_WATER_SHIFT) |
(0x3 << DMA_RWCTRL_WRITE_WATER_SHIFT) |
(1 << 23);
} else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) {
/* 5780 always in PCIX mode */
tp->dma_rwctrl |= 0x00144000;
......@@ -12016,6 +12047,9 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
tg3_full_unlock(tp);
/* Save MSI address and data for resume. */
pci_save_state(pdev);
err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
if (err) {
tg3_full_lock(tp, 0);
......
......@@ -1660,6 +1660,7 @@
#define MII_TG3_TEST1 0x1e
#define MII_TG3_TEST1_TRIM_EN 0x0010
#define MII_TG3_TEST1_CRC_EN 0x8000
/* There are two ways to manage the TX descriptors on the tigon3.
* Either the descriptors are in host DMA'able memory, or they
......
......@@ -946,14 +946,14 @@ extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
xfrm_address_t *saddr, u8 proto);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family);
extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family);
extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
......
......@@ -108,6 +108,7 @@ static void port_carrier_check(struct work_struct *work)
spin_unlock_bh(&br->lock);
}
done:
dev_put(dev);
rtnl_unlock();
}
......@@ -161,7 +162,8 @@ static void del_nbp(struct net_bridge_port *p)
dev_set_promiscuity(dev, -1);
cancel_delayed_work(&p->carrier_check);
if (cancel_delayed_work(&p->carrier_check))
dev_put(dev);
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
......@@ -444,7 +446,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br);
br_features_recompute(br);
schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
if (schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE))
dev_hold(dev);
spin_unlock_bh(&br->lock);
dev_set_mtu(br->dev, br_min_mtu(br));
......
......@@ -56,7 +56,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
case NETDEV_CHANGE:
if (br->dev->flags & IFF_UP)
schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
if (schedule_delayed_work(&p->carrier_check,
BR_PORT_DEBOUNCE))
dev_hold(dev);
break;
case NETDEV_FEAT_CHANGE:
......
......@@ -871,7 +871,7 @@ static int __init ipip_init(void)
printk(banner);
if (xfrm4_tunnel_register(&ipip_handler)) {
if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN;
}
......@@ -893,7 +893,7 @@ static int __init ipip_init(void)
err2:
free_netdev(ipip_fb_tunnel_dev);
err1:
xfrm4_tunnel_deregister(&ipip_handler);
xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
goto out;
}
......@@ -913,7 +913,7 @@ static void __exit ipip_destroy_tunnels(void)
static void __exit ipip_fini(void)
{
if (xfrm4_tunnel_deregister(&ipip_handler))
if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
printk(KERN_INFO "ipip close: can't deregister tunnel\n");
rtnl_lock();
......
......@@ -80,6 +80,10 @@ static void send_reset(struct sk_buff *oldskb, int hook)
nskb->mark = 0;
skb_init_secmark(nskb);
skb_shinfo(nskb)->gso_size = 0;
skb_shinfo(nskb)->gso_segs = 0;
skb_shinfo(nskb)->gso_type = 0;
tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
/* Swap source and dest */
......
......@@ -481,7 +481,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
/* RFC1323: The window in SYN & SYN/ACK segments
* is never scaled.
*/
th->window = htons(tp->rcv_wnd);
th->window = htons(min(tp->rcv_wnd, 65535U));
} else {
th->window = htons(tcp_select_window(sk));
}
......@@ -2160,7 +2160,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
}
/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
th->window = htons(req->rcv_wnd);
th->window = htons(min(req->rcv_wnd, 65535U));
TCP_SKB_CB(skb)->when = tcp_time_stamp;
tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
......
......@@ -14,9 +14,10 @@
#include <net/xfrm.h>
static struct xfrm_tunnel *tunnel4_handlers;
static struct xfrm_tunnel *tunnel64_handlers;
static DEFINE_MUTEX(tunnel4_mutex);
int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
{
struct xfrm_tunnel **pprev;
int ret = -EEXIST;
......@@ -24,7 +25,8 @@ int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
mutex_lock(&tunnel4_mutex);
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
*pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority)
break;
if ((*pprev)->priority == priority)
......@@ -44,14 +46,15 @@ err:
EXPORT_SYMBOL(xfrm4_tunnel_register);
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family)
{
struct xfrm_tunnel **pprev;
int ret = -ENOENT;
mutex_lock(&tunnel4_mutex);
for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers;
*pprev; pprev = &(*pprev)->next) {
if (*pprev == handler) {
*pprev = handler->next;
ret = 0;
......@@ -86,6 +89,26 @@ drop:
return 0;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static int tunnel64_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
goto drop;
for (handler = tunnel64_handlers; handler; handler = handler->next)
if (!handler->handler(skb))
return 0;
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
drop:
kfree_skb(skb);
return 0;
}
#endif
static void tunnel4_err(struct sk_buff *skb, u32 info)
{
struct xfrm_tunnel *handler;
......@@ -101,17 +124,36 @@ static struct net_protocol tunnel4_protocol = {
.no_policy = 1,
};
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct net_protocol tunnel64_protocol = {
.handler = tunnel64_rcv,
.err_handler = tunnel4_err,
.no_policy = 1,
};
#endif
static int __init tunnel4_init(void)
{
if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
printk(KERN_ERR "tunnel4 init: can't add protocol\n");
return -EAGAIN;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
printk(KERN_ERR "tunnel64 init: can't add protocol\n");
inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
return -EAGAIN;
}
#endif
return 0;
}
static void __exit tunnel4_fini(void)
{
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
#endif
if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
}
......
......@@ -27,6 +27,7 @@ static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32
{
switch (nexthdr) {
case IPPROTO_IPIP:
case IPPROTO_IPV6:
*spi = skb->nh.iph->saddr;
*seq = 0;
return 0;
......@@ -70,7 +71,8 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
if (xfrm_nr == XFRM_MAX_DEPTH)
goto drop;
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, iph->protocol, AF_INET);
x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
iph->protocol != IPPROTO_IPV6 ? iph->protocol : IPPROTO_IPIP, AF_INET);
if (x == NULL)
goto drop;
......
......@@ -95,6 +95,7 @@ static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
switch(iph->protocol){
case IPPROTO_IPIP:
break;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
case IPPROTO_IPV6:
break;
......
......@@ -64,24 +64,45 @@ static struct xfrm_tunnel xfrm_tunnel_handler = {
.priority = 2,
};
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static struct xfrm_tunnel xfrm64_tunnel_handler = {
.handler = xfrm4_rcv,
.err_handler = xfrm_tunnel_err,
.priority = 2,
};
#endif
static int __init ipip_init(void)
{
if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
printk(KERN_INFO "ipip init: can't add xfrm type\n");
return -EAGAIN;
}
if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
printk(KERN_INFO "ipip init: can't add xfrm handler\n");
if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n");
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n");
xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
#endif
return 0;
}
static void __exit ipip_fini(void)
{
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n");
#endif
if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n");
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
}
......
......@@ -156,6 +156,7 @@ config INET6_XFRM_MODE_ROUTEOPTIMIZATION
config IPV6_SIT
tristate "IPv6: IPv6-in-IPv4 tunnel (SIT driver)"
depends on IPV6
select INET_TUNNEL
default y
---help---
Tunneling means encapsulating data of one protocol type within
......
......@@ -172,7 +172,7 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
const struct in6_addr *saddr = &np->daddr;
const int dif = sk->sk_bound_dev_if;
const __portpair ports = INET_COMBINED_PORTS(inet->dport, lport);
const unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr,
const unsigned int hash = inet6_ehashfn(daddr, lport, saddr,
inet->dport);
struct inet_ehash_bucket *head = inet_ehash_bucket(hinfo, hash);
struct sock *sk2;
......
......@@ -1128,7 +1128,7 @@ static int __init ip6_tunnel_init(void)
{
int err;
if (xfrm6_tunnel_register(&ip6ip6_handler)) {
if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
return -EAGAIN;
}
......@@ -1147,7 +1147,7 @@ static int __init ip6_tunnel_init(void)
}
return 0;
fail:
xfrm6_tunnel_deregister(&ip6ip6_handler);
xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
return err;
}
......@@ -1171,7 +1171,7 @@ static void __exit ip6ip6_destroy_tunnels(void)
static void __exit ip6_tunnel_cleanup(void)
{
if (xfrm6_tunnel_deregister(&ip6ip6_handler))
if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
rtnl_lock();
......
......@@ -216,7 +216,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev)
}
static void ipip6_err(struct sk_buff *skb, u32 info)
static int ipip6_err(struct sk_buff *skb, u32 info)
{
#ifndef I_WISH_WORLD_WERE_PERFECT
......@@ -228,21 +228,22 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct ip_tunnel *t;
int err;
switch (type) {
default:
case ICMP_PARAMETERPROB:
return;
return 0;
case ICMP_DEST_UNREACH:
switch (code) {
case ICMP_SR_FAILED:
case ICMP_PORT_UNREACH:
/* Impossible event. */
return;
return 0;
case ICMP_FRAG_NEEDED:
/* Soft state for pmtu is maintained by IP core. */
return;
return 0;
default:
/* All others are translated to HOST_UNREACH.
rfc2003 contains "deep thoughts" about NET_UNREACH,
......@@ -253,14 +254,18 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
break;
case ICMP_TIME_EXCEEDED:
if (code != ICMP_EXC_TTL)
return;
return 0;
break;
}
err = -ENOENT;
read_lock(&ipip6_lock);
t = ipip6_tunnel_lookup(iph->daddr, iph->saddr);
if (t == NULL || t->parms.iph.daddr == 0)
goto out;
err = 0;
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
goto out;
......@@ -271,7 +276,7 @@ static void ipip6_err(struct sk_buff *skb, u32 info)
t->err_time = jiffies;
out:
read_unlock(&ipip6_lock);
return;
return err;
#else
struct iphdr *iph = (struct iphdr*)dp;
int hlen = iph->ihl<<2;
......@@ -332,7 +337,7 @@ out:
/* Prepare fake skb to feed it to icmpv6_send */
skb2 = skb_clone(skb, GFP_ATOMIC);
if (skb2 == NULL)
return;
return 0;
dst_release(skb2->dst);
skb2->dst = NULL;
skb_pull(skb2, skb->data - (u8*)iph6);
......@@ -355,7 +360,7 @@ out:
}
}
kfree_skb(skb2);
return;
return 0;
#endif
}
......@@ -791,9 +796,10 @@ static int __init ipip6_fb_tunnel_init(struct net_device *dev)
return 0;
}
static struct net_protocol sit_protocol = {
static struct xfrm_tunnel sit_handler = {
.handler = ipip6_rcv,
.err_handler = ipip6_err,
.priority = 1,
};
static void __exit sit_destroy_tunnels(void)
......@@ -812,7 +818,7 @@ static void __exit sit_destroy_tunnels(void)
static void __exit sit_cleanup(void)
{
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
rtnl_lock();
sit_destroy_tunnels();
......@@ -826,7 +832,7 @@ static int __init sit_init(void)
printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n");
if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) {
if (xfrm4_tunnel_register(&sit_handler, AF_INET6) < 0) {
printk(KERN_INFO "sit init: Can't add protocol\n");
return -EAGAIN;
}
......@@ -848,7 +854,7 @@ static int __init sit_init(void)
err2:
free_netdev(ipip6_fb_tunnel_dev);
err1:
inet_del_protocol(&sit_protocol, IPPROTO_IPV6);
xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
goto out;
}
......
......@@ -30,9 +30,10 @@
#include <net/xfrm.h>
static struct xfrm6_tunnel *tunnel6_handlers;
static struct xfrm6_tunnel *tunnel46_handlers;
static DEFINE_MUTEX(tunnel6_mutex);
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
{
struct xfrm6_tunnel **pprev;
int ret = -EEXIST;
......@@ -40,7 +41,8 @@ int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
mutex_lock(&tunnel6_mutex);
for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers;
*pprev; pprev = &(*pprev)->next) {
if ((*pprev)->priority > priority)
break;
if ((*pprev)->priority == priority)
......@@ -60,14 +62,15 @@ err: