X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Fsit.c;h=77b7b091143887b1cf5528365453e9ed696a17eb;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=2fac873fdd3d38dbd9b961a97bd935066ad2c1c3;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 2fac873fd..77b7b0911 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -18,8 +18,8 @@ * Nate Thompson : 6to4 support */ -#include #include +#include #include #include #include @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include /* This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c @@ -58,7 +60,7 @@ */ #define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) +#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); @@ -72,9 +74,9 @@ static struct ip_tunnel *tunnels_l[HASH_SIZE]; static struct ip_tunnel *tunnels_wc[1]; static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunnels_r_l }; -static rwlock_t ipip6_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(ipip6_lock); -static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) +static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -100,8 +102,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) { - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; + __be32 remote = t->parms.iph.daddr; + __be32 local = t->parms.iph.saddr; unsigned h = 0; int prio = 0; @@ -134,16 +136,16 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) { struct ip_tunnel **tp = ipip6_bucket(t); - write_lock_bh(&ipip6_lock); t->next = *tp; - write_unlock_bh(&ipip6_lock); + write_lock_bh(&ipip6_lock); *tp = t; + write_unlock_bh(&ipip6_lock); } static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) { - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; + __be32 remote = parms->iph.daddr; + __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = 0; @@ -182,7 +184,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int if (dev == NULL) return NULL; - nt = dev->priv; + nt = netdev_priv(dev); dev->init = ipip6_tunnel_init; nt->parms = *parms; @@ -194,7 +196,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); ipip6_tunnel_link(nt); - /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: @@ -209,7 +210,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) write_unlock_bh(&ipip6_lock); dev_put(dev); } else { - ipip6_tunnel_unlink((struct ip_tunnel*)dev->priv); + ipip6_tunnel_unlink(netdev_priv(dev)); dev_put(dev); } } @@ -345,7 +346,7 @@ out: rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { - struct ip_tunnel * t = (struct ip_tunnel*)rt6i->rt6i_dev->priv; + struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { rel_type = ICMPV6_DEST_UNREACH; rel_code = ICMPV6_ADDR_UNREACH; @@ -360,8 +361,7 @@ out: static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) { - if (INET_ECN_is_ce(iph->tos) && - INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h))) + if (INET_ECN_is_ce(iph->tos)) IP6_ECN_set_ce(skb->nh.ipv6h); } @@ -380,7 +380,7 @@ static int ipip6_rcv(struct sk_buff *skb) secpath_reset(skb); skb->mac.raw = skb->nh.raw; skb->nh.raw = skb->data; - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + IPCB(skb)->flags = 0; skb->protocol = htons(ETH_P_IPV6); skb->pkt_type = PACKET_HOST; tunnel->stat.rx_packets++; @@ -388,20 +388,14 @@ static int ipip6_rcv(struct sk_buff *skb) skb->dev = tunnel->dev; dst_release(skb->dst); skb->dst = NULL; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); ipip6_ecn_decapsulate(iph, skb); netif_rx(skb); read_unlock(&ipip6_lock); return 0; } - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0); + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); kfree_skb(skb); read_unlock(&ipip6_lock); out: @@ -411,9 +405,9 @@ out: /* Returns the embedded IPv4 address if the IPv6 address comes from 6to4 (RFC 3056) addr space */ -static inline u32 try_6to4(struct in6_addr *v6dst) +static inline __be32 try_6to4(struct in6_addr *v6dst) { - u32 dst = 0; + __be32 dst = 0; if (v6dst->s6_addr16[0] == htons(0x2002)) { /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ @@ -429,7 +423,7 @@ static inline u32 try_6to4(struct in6_addr *v6dst) static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) { - struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct net_device_stats *stats = &tunnel->stat; struct iphdr *tiph = &tunnel->parms.iph; struct ipv6hdr *iph6 = skb->nh.ipv6h; @@ -438,7 +432,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ - u32 dst = tiph->daddr; + __be32 dst = tiph->daddr; int mtu; struct in6_addr *addr6; int addr_type; @@ -493,6 +487,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } } if (rt->rt_type != RTN_UNICAST) { + ip_rt_put(rt); tunnel->stat.tx_carrier_errors++; goto tx_error_icmp; } @@ -505,9 +500,9 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) } if (tiph->frag_off) - mtu = dst_pmtu(&rt->u.dst) - sizeof(struct iphdr); + mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); else - mtu = skb->dst ? dst_pmtu(skb->dst) : dev->mtu; + mtu = skb->dst ? dst_mtu(skb->dst) : dev->mtu; if (mtu < 68) { tunnel->stat.collisions++; @@ -557,6 +552,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->h.raw = skb->nh.raw; skb->nh.raw = skb_push(skb, sizeof(struct iphdr)); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); + IPCB(skb)->flags = 0; dst_release(skb->dst); skb->dst = &rt->u.dst; @@ -573,20 +569,14 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) iph->frag_off = 0; iph->protocol = IPPROTO_IPV6; - iph->tos = INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6)); + iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); iph->daddr = rt->rt_dst; iph->saddr = rt->rt_src; if ((iph->ttl = tiph->ttl) == 0) iph->ttl = iph6->hop_limit; -#ifdef CONFIG_NETFILTER - nf_conntrack_put(skb->nfct); - skb->nfct = NULL; -#ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; -#endif -#endif + nf_reset(skb); IPTUNNEL_XMIT(); tunnel->recursion--; @@ -619,7 +609,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip6_tunnel_locate(&p, 0); } if (t == NULL) - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); memcpy(&p, &t->parms, sizeof(p)); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) err = -EFAULT; @@ -656,7 +646,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; break; } - t = (struct ip_tunnel*)dev->priv; + t = netdev_priv(dev); ipip6_tunnel_unlink(t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; @@ -692,7 +682,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == ipip6_fb_tunnel_dev->priv) + if (t == netdev_priv(ipip6_fb_tunnel_dev)) goto done; dev = t->dev; } @@ -709,7 +699,7 @@ done: static struct net_device_stats *ipip6_tunnel_get_stats(struct net_device *dev) { - return &(((struct ip_tunnel*)dev->priv)->stat); + return &(((struct ip_tunnel*)netdev_priv(dev))->stat); } static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) @@ -732,7 +722,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->type = ARPHRD_SIT; dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); - dev->mtu = 1500 - sizeof(struct iphdr); + dev->mtu = ETH_DATA_LEN - sizeof(struct iphdr); dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; @@ -744,7 +734,7 @@ static int ipip6_tunnel_init(struct net_device *dev) struct ip_tunnel *tunnel; struct iphdr *iph; - tunnel = (struct ip_tunnel*)dev->priv; + tunnel = netdev_priv(dev); iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -782,9 +772,9 @@ static int ipip6_tunnel_init(struct net_device *dev) return 0; } -int __init ipip6_fb_tunnel_init(struct net_device *dev) +static int __init ipip6_fb_tunnel_init(struct net_device *dev) { - struct ip_tunnel *tunnel = dev->priv; + struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; tunnel->dev = dev; @@ -800,18 +790,36 @@ int __init ipip6_fb_tunnel_init(struct net_device *dev) return 0; } -static struct inet_protocol sit_protocol = { +static struct net_protocol sit_protocol = { .handler = ipip6_rcv, .err_handler = ipip6_err, }; -void __exit sit_cleanup(void) +static void __exit sit_destroy_tunnels(void) +{ + int prio; + + for (prio = 1; prio < 4; prio++) { + int h; + for (h = 0; h < HASH_SIZE; h++) { + struct ip_tunnel *t; + while ((t = tunnels[prio][h]) != NULL) + unregister_netdevice(t->dev); + } + } +} + +static void __exit sit_cleanup(void) { inet_del_protocol(&sit_protocol, IPPROTO_IPV6); - unregister_netdev(ipip6_fb_tunnel_dev); + + rtnl_lock(); + sit_destroy_tunnels(); + unregister_netdevice(ipip6_fb_tunnel_dev); + rtnl_unlock(); } -int __init sit_init(void) +static int __init sit_init(void) { int err; @@ -826,18 +834,24 @@ int __init sit_init(void) ipip6_tunnel_setup); if (!ipip6_fb_tunnel_dev) { err = -ENOMEM; - goto fail; + goto err1; } ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; if ((err = register_netdev(ipip6_fb_tunnel_dev))) - goto fail; + goto err2; out: return err; - fail: - inet_del_protocol(&sit_protocol, IPPROTO_IPV6); + err2: free_netdev(ipip6_fb_tunnel_dev); + err1: + inet_del_protocol(&sit_protocol, IPPROTO_IPV6); goto out; } + +module_init(sit_init); +module_exit(sit_cleanup); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("sit0");