From 606a2b4862d4be31fa55cad89871fe52a422d511 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Tue, 4 Mar 2008 13:45:59 -0800 Subject: [NETNS][IPV6] route6 - Pass the network namespace parameter to rt6_lookup Add a network namespace parameter to rt6_lookup(). Signed-off-by: Daniel Lezcano Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/sit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1656c003b98..68720aa63f9 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -339,11 +339,11 @@ out: skb_reset_network_header(skb2); /* Try to guess incoming interface */ - rt6i = rt6_lookup(&iph6->saddr, NULL, NULL, 0); + rt6i = rt6_lookup(&init_net, &iph6->saddr, NULL, NULL, 0); if (rt6i && rt6i->rt6i_dev) { skb2->dev = rt6i->rt6i_dev; - rt6i = rt6_lookup(&iph6->daddr, &iph6->saddr, NULL, 0); + rt6i = rt6_lookup(&init_net, &iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); -- cgit v1.2.3 From 4591db4f37618f37a9f1f25d291c3c7a43a15a21 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Wed, 5 Mar 2008 10:48:10 -0800 Subject: [NETNS][IPV6] route6 - add netns parameter to ip6_route_output Add an netns parameter to ip6_route_output. That will allow to access to the right routing table for outgoing traffic. Signed-off-by: Daniel Lezcano Signed-off-by: Benjamin Thery Signed-off-by: David S. Miller --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 68720aa63f9..1b8196c8d14 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -393,7 +393,7 @@ isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev) fl.oif = dev->ifindex; security_skb_classify_flow(skb, &fl); - dst = ip6_route_output(NULL, &fl); + dst = ip6_route_output(&init_net, NULL, &fl); if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { addr6 = (struct in6_addr*)&neigh->primary_key; -- cgit v1.2.3 From fadf6bf06069138f8e97c9a963be38348ba2708b Mon Sep 17 00:00:00 2001 From: "Templin, Fred L" Date: Tue, 11 Mar 2008 18:35:59 -0400 Subject: [IPV6] SIT: Add PRL management for ISATAP. This patch updates the Linux the Intra-Site Automatic Tunnel Addressing Protocol (ISATAP) implementation. It places the ISATAP potential router list (PRL) in the kernel and adds three new private ioctls for PRL management. [Add several changes of structure name, constant names etc. - yoshfuji] Signed-off-by: Fred L. Templin Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/sit.c | 186 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 142 insertions(+), 44 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 1b8196c8d14..4786419ade0 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -16,7 +16,7 @@ * Changes: * Roger Venning : 6to4 support * Nate Thompson : 6to4 support - * Fred L. Templin : isatap support + * Fred Templin : isatap support */ #include @@ -197,6 +197,119 @@ failed: return NULL; } +static struct ip_tunnel_prl_entry * +ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) +{ + struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL; + + for (p = t->prl; p; p = p->next) + if (p->entry.addr == addr) + break; + return p; + +} + +static int +ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) +{ + struct ip_tunnel_prl_entry *p; + + for (p = t->prl; p; p = p->next) { + if (p->entry.addr == a->addr) { + if (chg) { + p->entry = *a; + return 0; + } + return -EEXIST; + } + } + + if (chg) + return -ENXIO; + + p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL); + if (!p) + return -ENOBUFS; + + p->entry = *a; + p->next = t->prl; + t->prl = p; + return 0; +} + +static int +ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) +{ + struct ip_tunnel_prl_entry *x, **p; + + if (a) { + for (p = &t->prl; *p; p = &(*p)->next) { + if ((*p)->entry.addr == a->addr) { + x = *p; + *p = x->next; + kfree(x); + return 0; + } + } + return -ENXIO; + } else { + while (t->prl) { + x = t->prl; + t->prl = t->prl->next; + kfree(x); + } + } + return 0; +} + +/* copied directly from anycast.c */ +static int +ipip6_onlink(struct in6_addr *addr, struct net_device *dev) +{ + struct inet6_dev *idev; + struct inet6_ifaddr *ifa; + int onlink; + + onlink = 0; + rcu_read_lock(); + idev = __in6_dev_get(dev); + if (idev) { + read_lock_bh(&idev->lock); + for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { + onlink = ipv6_prefix_equal(addr, &ifa->addr, + ifa->prefix_len); + if (onlink) + break; + } + read_unlock_bh(&idev->lock); + } + rcu_read_unlock(); + return onlink; +} + +static int +isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) +{ + struct ip_tunnel_prl_entry *p = ipip6_tunnel_locate_prl(t, iph->saddr); + int ok = 1; + + if (p) { + if (p->entry.flags & PRL_DEFAULT) + skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; + else + skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; + } else { + struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; + if (ipv6_addr_is_isatap(addr6) && + (addr6->s6_addr32[3] == iph->saddr) && + ipip6_onlink(addr6, t->dev)) + skb->ndisc_nodetype = NDISC_NODETYPE_HOST; + else + ok = 0; + } + return ok; +} + static void ipip6_tunnel_uninit(struct net_device *dev) { if (dev == ipip6_fb_tunnel_dev) { @@ -206,6 +319,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) dev_put(dev); } else { ipip6_tunnel_unlink(netdev_priv(dev)); + ipip6_tunnel_del_prl(netdev_priv(dev), 0); dev_put(dev); } } @@ -365,48 +479,6 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) IP6_ECN_set_ce(ipv6_hdr(skb)); } -/* ISATAP (RFC4214) - check source address */ -static int -isatap_srcok(struct sk_buff *skb, struct iphdr *iph, struct net_device *dev) -{ - struct neighbour *neigh; - struct dst_entry *dst; - struct rt6_info *rt; - struct flowi fl; - struct in6_addr *addr6; - struct in6_addr rtr; - struct ipv6hdr *iph6; - int ok = 0; - - /* from onlink default router */ - ipv6_addr_set(&rtr, htonl(0xFE800000), 0, 0, 0); - ipv6_isatap_eui64(rtr.s6_addr + 8, iph->saddr); - if ((rt = rt6_get_dflt_router(&rtr, dev))) { - dst_release(&rt->u.dst); - return 1; - } - - iph6 = ipv6_hdr(skb); - memset(&fl, 0, sizeof(fl)); - fl.proto = iph6->nexthdr; - ipv6_addr_copy(&fl.fl6_dst, &iph6->saddr); - fl.oif = dev->ifindex; - security_skb_classify_flow(skb, &fl); - - dst = ip6_route_output(&init_net, NULL, &fl); - if (!dst->error && (dst->dev == dev) && (neigh = dst->neighbour)) { - - addr6 = (struct in6_addr*)&neigh->primary_key; - - /* from correct previous hop */ - if (ipv6_addr_is_isatap(addr6) && - (addr6->s6_addr32[3] == iph->saddr)) - ok = 1; - } - dst_release(dst); - return ok; -} - static int ipip6_rcv(struct sk_buff *skb) { struct iphdr *iph; @@ -427,7 +499,7 @@ static int ipip6_rcv(struct sk_buff *skb) skb->pkt_type = PACKET_HOST; if ((tunnel->dev->priv_flags & IFF_ISATAP) && - !isatap_srcok(skb, iph, tunnel->dev)) { + !isatap_chksrc(skb, iph, tunnel)) { tunnel->stat.rx_errors++; read_unlock(&ipip6_lock); kfree_skb(skb); @@ -707,6 +779,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) { int err = 0; struct ip_tunnel_parm p; + struct ip_tunnel_prl prl; struct ip_tunnel *t; switch (cmd) { @@ -806,6 +879,31 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = 0; break; + case SIOCADDPRL: + case SIOCDELPRL: + case SIOCCHGPRL: + err = -EPERM; + if (!capable(CAP_NET_ADMIN)) + goto done; + err = -EINVAL; + if (dev == ipip6_fb_tunnel_dev) + goto done; + err = -EFAULT; + if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) + goto done; + err = -ENOENT; + if (!(t = netdev_priv(dev))) + goto done; + + ipip6_tunnel_unlink(t); + if (cmd == SIOCDELPRL) + err = ipip6_tunnel_del_prl(t, &prl); + else + err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); + ipip6_tunnel_link(t); + netdev_state_change(dev); + break; + default: err = -EINVAL; } -- cgit v1.2.3 From 3fcfa12904e83cc291cf2b7b05ff2530068920a4 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 22 Mar 2008 17:42:57 +0900 Subject: [IPV6] SIT: Fix locking issues in PRL management. To protect PRL list, use ipip6_lock. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/sit.c | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 4786419ade0..ee0cc285169 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -198,7 +198,7 @@ failed: } static struct ip_tunnel_prl_entry * -ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) +__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) { struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL; @@ -213,34 +213,46 @@ static int ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) { struct ip_tunnel_prl_entry *p; + int err = 0; + + write_lock(&ipip6_lock); for (p = t->prl; p; p = p->next) { if (p->entry.addr == a->addr) { - if (chg) { - p->entry = *a; - return 0; - } - return -EEXIST; + if (chg) + goto update; + err = -EEXIST; + goto out; } } - if (chg) - return -ENXIO; + if (chg) { + err = -ENXIO; + goto out; + } p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL); - if (!p) - return -ENOBUFS; + if (!p) { + err = -ENOBUFS; + goto out; + } - p->entry = *a; p->next = t->prl; t->prl = p; - return 0; +update: + p->entry = *a; +out: + write_unlock(&ipip6_lock); + return err; } static int ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) { struct ip_tunnel_prl_entry *x, **p; + int err = 0; + + write_lock(&ipip6_lock); if (a) { for (p = &t->prl; *p; p = &(*p)->next) { @@ -248,10 +260,10 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) x = *p; *p = x->next; kfree(x); - return 0; + goto out; } } - return -ENXIO; + err = -ENXIO; } else { while (t->prl) { x = t->prl; @@ -259,6 +271,8 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) kfree(x); } } +out: + write_unlock(&ipip6_lock); return 0; } @@ -290,9 +304,11 @@ ipip6_onlink(struct in6_addr *addr, struct net_device *dev) static int isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) { - struct ip_tunnel_prl_entry *p = ipip6_tunnel_locate_prl(t, iph->saddr); + struct ip_tunnel_prl_entry *p; int ok = 1; + read_lock(&ipip6_lock); + p = __ipip6_tunnel_locate_prl(t, iph->saddr); if (p) { if (p->entry.flags & PRL_DEFAULT) skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; @@ -307,6 +323,7 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) else ok = 0; } + read_unlock(&ipip6_lock); return ok; } @@ -895,12 +912,10 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (!(t = netdev_priv(dev))) goto done; - ipip6_tunnel_unlink(t); if (cmd == SIOCDELPRL) err = ipip6_tunnel_del_prl(t, &prl); else err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); - ipip6_tunnel_link(t); netdev_state_change(dev); break; -- cgit v1.2.3 From 0009ae1f50fb10178b5f54216ce567f3cb1d7267 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 22 Mar 2008 17:50:59 +0900 Subject: [IPV6] SIT: Disallow 0.0.0.0 in PRL and Flush PRL if given for DEL. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/sit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index ee0cc285169..84c1ed246af 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -215,6 +215,9 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) struct ip_tunnel_prl_entry *p; int err = 0; + if (a->addr == htonl(INADDR_ANY)) + return -EINVAL; + write_lock(&ipip6_lock); for (p = t->prl; p; p = p->next) { @@ -254,7 +257,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) write_lock(&ipip6_lock); - if (a) { + if (a && a->addr != htonl(INADDR_ANY)) { for (p = &t->prl; *p; p = &(*p)->next) { if ((*p)->entry.addr == a->addr) { x = *p; -- cgit v1.2.3 From 300aaeeaab5f447fcf40e911afe96df3de28f0db Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Mon, 24 Mar 2008 18:28:39 +0900 Subject: [IPV6] SIT: Add SIOCGETPRL ioctl to get/dump PRL. Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/sit.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 87 insertions(+), 9 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 84c1ed246af..08a483a8de5 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -203,12 +203,73 @@ __ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL; for (p = t->prl; p; p = p->next) - if (p->entry.addr == addr) + if (p->addr == addr) break; return p; } +static int ipip6_tunnel_get_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) +{ + struct ip_tunnel_prl *kp; + struct ip_tunnel_prl_entry *prl; + unsigned int cmax, c = 0, ca, len; + int ret = 0; + + cmax = a->datalen / sizeof(*a); + if (cmax > 1 && a->addr != htonl(INADDR_ANY)) + cmax = 1; + + /* For simple GET or for root users, + * we try harder to allocate. + */ + kp = (cmax <= 1 || capable(CAP_NET_ADMIN)) ? + kcalloc(cmax, sizeof(*kp), GFP_KERNEL) : + NULL; + + read_lock(&ipip6_lock); + + ca = t->prl_count < cmax ? t->prl_count : cmax; + + if (!kp) { + /* We don't try hard to allocate much memory for + * non-root users. + * For root users, retry allocating enough memory for + * the answer. + */ + kp = kcalloc(ca, sizeof(*kp), GFP_ATOMIC); + if (!kp) { + ret = -ENOMEM; + goto out; + } + } + + c = 0; + for (prl = t->prl; prl; prl = prl->next) { + if (c > cmax) + break; + if (a->addr != htonl(INADDR_ANY) && prl->addr != a->addr) + continue; + kp[c].addr = prl->addr; + kp[c].flags = prl->flags; + c++; + if (a->addr != htonl(INADDR_ANY)) + break; + } +out: + read_unlock(&ipip6_lock); + + len = sizeof(*kp) * c; + ret = len ? copy_to_user(a->data, kp, len) : 0; + + kfree(kp); + if (ret) + return -EFAULT; + + a->datalen = len; + return 0; +} + static int ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) { @@ -221,7 +282,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) write_lock(&ipip6_lock); for (p = t->prl; p; p = p->next) { - if (p->entry.addr == a->addr) { + if (p->addr == a->addr) { if (chg) goto update; err = -EEXIST; @@ -242,8 +303,10 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) p->next = t->prl; t->prl = p; + t->prl_count++; update: - p->entry = *a; + p->addr = a->addr; + p->flags = a->flags; out: write_unlock(&ipip6_lock); return err; @@ -259,10 +322,11 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) if (a && a->addr != htonl(INADDR_ANY)) { for (p = &t->prl; *p; p = &(*p)->next) { - if ((*p)->entry.addr == a->addr) { + if ((*p)->addr == a->addr) { x = *p; *p = x->next; kfree(x); + t->prl_count--; goto out; } } @@ -272,6 +336,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) x = t->prl; t->prl = t->prl->next; kfree(x); + t->prl_count--; } } out: @@ -313,7 +378,7 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) read_lock(&ipip6_lock); p = __ipip6_tunnel_locate_prl(t, iph->saddr); if (p) { - if (p->entry.flags & PRL_DEFAULT) + if (p->flags & PRL_DEFAULT) skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; else skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; @@ -899,11 +964,12 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = 0; break; + case SIOCGETPRL: case SIOCADDPRL: case SIOCDELPRL: case SIOCCHGPRL: err = -EPERM; - if (!capable(CAP_NET_ADMIN)) + if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) goto done; err = -EINVAL; if (dev == ipip6_fb_tunnel_dev) @@ -915,11 +981,23 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (!(t = netdev_priv(dev))) goto done; - if (cmd == SIOCDELPRL) + switch (cmd) { + case SIOCGETPRL: + err = ipip6_tunnel_get_prl(t, &prl); + if (!err && copy_to_user(ifr->ifr_ifru.ifru_data, + &prl, sizeof(prl))) + err = -EFAULT; + break; + case SIOCDELPRL: err = ipip6_tunnel_del_prl(t, &prl); - else + break; + case SIOCADDPRL: + case SIOCCHGPRL: err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); - netdev_state_change(dev); + break; + } + if (cmd != SIOCGETPRL) + netdev_state_change(dev); break; default: -- cgit v1.2.3 From 52eeeb8481d705e61e2e9aae974e7799a93783e9 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sat, 15 Mar 2008 22:54:23 -0400 Subject: [IPV6]: Unify ip6_onlink() and ipip6_onlink(). Both are identical, let's create ipv6_chk_prefix() and use it in both places. --- net/ipv6/sit.c | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 08a483a8de5..cc16fe07bbf 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -344,31 +344,6 @@ out: return 0; } -/* copied directly from anycast.c */ -static int -ipip6_onlink(struct in6_addr *addr, struct net_device *dev) -{ - struct inet6_dev *idev; - struct inet6_ifaddr *ifa; - int onlink; - - onlink = 0; - rcu_read_lock(); - idev = __in6_dev_get(dev); - if (idev) { - read_lock_bh(&idev->lock); - for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { - onlink = ipv6_prefix_equal(addr, &ifa->addr, - ifa->prefix_len); - if (onlink) - break; - } - read_unlock_bh(&idev->lock); - } - rcu_read_unlock(); - return onlink; -} - static int isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) { @@ -386,7 +361,7 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; if (ipv6_addr_is_isatap(addr6) && (addr6->s6_addr32[3] == iph->saddr) && - ipip6_onlink(addr6, t->dev)) + ipv6_chk_prefix(addr6, t->dev)) skb->ndisc_nodetype = NDISC_NODETYPE_HOST; else ok = 0; -- cgit v1.2.3 From 02e10b90cd478bda81b4644102b0009bcd1d14ab Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Thu, 10 Apr 2008 15:41:27 +0900 Subject: [IPV6] SIT: Sparse: Use NULL pointer instead of 0. | net/ipv6/sit.c:382:42: warning: Using plain integer as NULL pointer Signed-off-by: YOSHIFUJI Hideaki --- net/ipv6/sit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index cc16fe07bbf..91e46fbe6ce 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -379,7 +379,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) dev_put(dev); } else { ipip6_tunnel_unlink(netdev_priv(dev)); - ipip6_tunnel_del_prl(netdev_priv(dev), 0); + ipip6_tunnel_del_prl(netdev_priv(dev), NULL); dev_put(dev); } } -- cgit v1.2.3 From 8190d9009a74e7862b31874cd347b394d390cc6e Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:15:17 -0700 Subject: [SIT]: Introduce empty struct sit_net and init/exit net ops. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 91e46fbe6ce..aa6efc2ab55 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -52,6 +52,8 @@ #include #include #include +#include +#include /* This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c @@ -66,6 +68,10 @@ static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); static void ipip6_tunnel_setup(struct net_device *dev); +static int sit_net_id; +struct sit_net { +}; + static struct net_device *ipip6_fb_tunnel_dev; static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; @@ -1068,6 +1074,41 @@ static void __exit sit_destroy_tunnels(void) } } +static int sit_init_net(struct net *net) +{ + int err; + struct sit_net *sitn; + + err = -ENOMEM; + sitn = kmalloc(sizeof(struct sit_net), GFP_KERNEL); + if (sitn == NULL) + goto err_alloc; + + err = net_assign_generic(net, sit_net_id, sitn); + if (err < 0) + goto err_assign; + + return 0; + +err_assign: + kfree(sitn); +err_alloc: + return err; +} + +static void sit_exit_net(struct net *net) +{ + struct sit_net *sitn; + + sitn = net_generic(net, sit_net_id); + kfree(sitn); +} + +static struct pernet_operations sit_net_ops = { + .init = sit_init_net, + .exit = sit_exit_net, +}; + static void __exit sit_cleanup(void) { xfrm4_tunnel_deregister(&sit_handler, AF_INET6); @@ -1076,6 +1117,8 @@ static void __exit sit_cleanup(void) sit_destroy_tunnels(); unregister_netdevice(ipip6_fb_tunnel_dev); rtnl_unlock(); + + unregister_pernet_gen_device(sit_net_id, &sit_net_ops); } static int __init sit_init(void) @@ -1101,6 +1144,10 @@ static int __init sit_init(void) if ((err = register_netdev(ipip6_fb_tunnel_dev))) goto err2; + err = register_pernet_gen_device(&sit_net_id, &sit_net_ops); + if (err < 0) + goto err3; + out: return err; err2: @@ -1108,6 +1155,9 @@ static int __init sit_init(void) err1: xfrm4_tunnel_deregister(&sit_handler, AF_INET6); goto out; +err3: + unregister_netdevice(ipip6_fb_tunnel_dev); + goto err1; } module_init(sit_init); -- cgit v1.2.3 From ca8def1483a7621503247e28d1ca5dace9b945fe Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:15:39 -0700 Subject: [SIT]: Add net/sit_net argument to some functions. ... to make them prepared for future hashes and fallback device move on the struct sit_net. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index aa6efc2ab55..66cf0be4b67 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -82,7 +82,8 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne static DEFINE_RWLOCK(ipip6_lock); -static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) +static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, + __be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -106,7 +107,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) return NULL; } -static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms) +static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn, + struct ip_tunnel_parm *parms) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; @@ -124,16 +126,17 @@ static struct ip_tunnel **__ipip6_bucket(struct ip_tunnel_parm *parms) return &tunnels[prio][h]; } -static inline struct ip_tunnel **ipip6_bucket(struct ip_tunnel *t) +static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn, + struct ip_tunnel *t) { - return __ipip6_bucket(&t->parms); + return __ipip6_bucket(sitn, &t->parms); } -static void ipip6_tunnel_unlink(struct ip_tunnel *t) +static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t) { struct ip_tunnel **tp; - for (tp = ipip6_bucket(t); *tp; tp = &(*tp)->next) { + for (tp = ipip6_bucket(sitn, t); *tp; tp = &(*tp)->next) { if (t == *tp) { write_lock_bh(&ipip6_lock); *tp = t->next; @@ -143,9 +146,9 @@ static void ipip6_tunnel_unlink(struct ip_tunnel *t) } } -static void ipip6_tunnel_link(struct ip_tunnel *t) +static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t) { - struct ip_tunnel **tp = ipip6_bucket(t); + struct ip_tunnel **tp = ipip6_bucket(sitn, t); t->next = *tp; write_lock_bh(&ipip6_lock); @@ -153,15 +156,17 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) write_unlock_bh(&ipip6_lock); } -static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) +static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, + struct ip_tunnel_parm *parms, int create) { __be32 remote = parms->iph.daddr; __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; char name[IFNAMSIZ]; + struct sit_net *sitn = net_generic(net, sit_net_id); - for (tp = __ipip6_bucket(parms); (t = *tp) != NULL; tp = &t->next) { + for (tp = __ipip6_bucket(sitn, parms); (t = *tp) != NULL; tp = &t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) return t; } @@ -194,7 +199,7 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int dev_hold(dev); - ipip6_tunnel_link(nt); + ipip6_tunnel_link(sitn, nt); return nt; failed_free: @@ -378,13 +383,16 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) static void ipip6_tunnel_uninit(struct net_device *dev) { + struct net *net = dev_net(dev); + struct sit_net *sitn = net_generic(net, sit_net_id); + if (dev == ipip6_fb_tunnel_dev) { write_lock_bh(&ipip6_lock); tunnels_wc[0] = NULL; write_unlock_bh(&ipip6_lock); dev_put(dev); } else { - ipip6_tunnel_unlink(netdev_priv(dev)); + ipip6_tunnel_unlink(sitn, netdev_priv(dev)); ipip6_tunnel_del_prl(netdev_priv(dev), NULL); dev_put(dev); } @@ -436,7 +444,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) err = -ENOENT; read_lock(&ipip6_lock); - t = ipip6_tunnel_lookup(iph->daddr, iph->saddr); + t = ipip6_tunnel_lookup(&init_net, iph->daddr, iph->saddr); if (t == NULL || t->parms.iph.daddr == 0) goto out; @@ -556,7 +564,8 @@ static int ipip6_rcv(struct sk_buff *skb) iph = ip_hdr(skb); read_lock(&ipip6_lock); - if ((tunnel = ipip6_tunnel_lookup(iph->saddr, iph->daddr)) != NULL) { + if ((tunnel = ipip6_tunnel_lookup(&init_net, + iph->saddr, iph->daddr)) != NULL) { secpath_reset(skb); skb->mac_header = skb->network_header; skb_reset_network_header(skb); @@ -847,6 +856,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) struct ip_tunnel_parm p; struct ip_tunnel_prl prl; struct ip_tunnel *t; + struct net *net = dev_net(dev); + struct sit_net *sitn = net_generic(net, sit_net_id); switch (cmd) { case SIOCGETTUNNEL: @@ -856,7 +867,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EFAULT; break; } - t = ipip6_tunnel_locate(&p, 0); + t = ipip6_tunnel_locate(net, &p, 0); } if (t == NULL) t = netdev_priv(dev); @@ -882,7 +893,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (p.iph.ttl) p.iph.frag_off |= htons(IP_DF); - t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL); + t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { if (t != NULL) { @@ -897,12 +908,12 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) break; } t = netdev_priv(dev); - ipip6_tunnel_unlink(t); + ipip6_tunnel_unlink(sitn, t); t->parms.iph.saddr = p.iph.saddr; t->parms.iph.daddr = p.iph.daddr; memcpy(dev->dev_addr, &p.iph.saddr, 4); memcpy(dev->broadcast, &p.iph.daddr, 4); - ipip6_tunnel_link(t); + ipip6_tunnel_link(sitn, t); netdev_state_change(dev); } } @@ -934,7 +945,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) goto done; err = -ENOENT; - if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) + if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL) goto done; err = -EPERM; if (t == netdev_priv(ipip6_fb_tunnel_dev)) -- cgit v1.2.3 From fcee5ec9fdd2b27bce2a6ae8cd8161ad9a8899df Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:15:59 -0700 Subject: [SIT]: Use proper net in hash-lookup functions. Replace introduced in the previous patch init_net stubs with the proper net pointer. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 66cf0be4b67..e85ddcd763d 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -444,7 +444,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) err = -ENOENT; read_lock(&ipip6_lock); - t = ipip6_tunnel_lookup(&init_net, iph->daddr, iph->saddr); + t = ipip6_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr); if (t == NULL || t->parms.iph.daddr == 0) goto out; @@ -564,7 +564,7 @@ static int ipip6_rcv(struct sk_buff *skb) iph = ip_hdr(skb); read_lock(&ipip6_lock); - if ((tunnel = ipip6_tunnel_lookup(&init_net, + if ((tunnel = ipip6_tunnel_lookup(dev_net(skb->dev), iph->saddr, iph->daddr)) != NULL) { secpath_reset(skb); skb->mac_header = skb->network_header; -- cgit v1.2.3 From cd3dbc194d6784624f21acbc622a75c92378ba5a Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:16:18 -0700 Subject: [SIT]: Make the fallback tunnel device per-net Allocate and register one in sit_init_net, use sitn->fb_tunnel_dev over the code and unregister one in sit_exit_net. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 61 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index e85ddcd763d..d0c1f2db7f2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -70,10 +70,9 @@ static void ipip6_tunnel_setup(struct net_device *dev); static int sit_net_id; struct sit_net { + struct net_device *fb_tunnel_dev; }; -static struct net_device *ipip6_fb_tunnel_dev; - static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; static struct ip_tunnel *tunnels_r[HASH_SIZE]; static struct ip_tunnel *tunnels_l[HASH_SIZE]; @@ -386,7 +385,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) struct net *net = dev_net(dev); struct sit_net *sitn = net_generic(net, sit_net_id); - if (dev == ipip6_fb_tunnel_dev) { + if (dev == sitn->fb_tunnel_dev) { write_lock_bh(&ipip6_lock); tunnels_wc[0] = NULL; write_unlock_bh(&ipip6_lock); @@ -862,7 +861,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGETTUNNEL: t = NULL; - if (dev == ipip6_fb_tunnel_dev) { + if (dev == sitn->fb_tunnel_dev) { if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { err = -EFAULT; break; @@ -895,7 +894,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) t = ipip6_tunnel_locate(net, &p, cmd == SIOCADDTUNNEL); - if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { + if (dev != sitn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { if (t != NULL) { if (t->dev != dev) { err = -EEXIST; @@ -940,7 +939,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (!capable(CAP_NET_ADMIN)) goto done; - if (dev == ipip6_fb_tunnel_dev) { + if (dev == sitn->fb_tunnel_dev) { err = -EFAULT; if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) goto done; @@ -948,7 +947,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if ((t = ipip6_tunnel_locate(net, &p, 0)) == NULL) goto done; err = -EPERM; - if (t == netdev_priv(ipip6_fb_tunnel_dev)) + if (t == netdev_priv(sitn->fb_tunnel_dev)) goto done; dev = t->dev; } @@ -964,7 +963,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) if (cmd != SIOCGETPRL && !capable(CAP_NET_ADMIN)) goto done; err = -EINVAL; - if (dev == ipip6_fb_tunnel_dev) + if (dev == sitn->fb_tunnel_dev) goto done; err = -EFAULT; if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) @@ -1047,7 +1046,7 @@ static int ipip6_tunnel_init(struct net_device *dev) return 0; } -static int __init ipip6_fb_tunnel_init(struct net_device *dev) +static int ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; @@ -1099,8 +1098,25 @@ static int sit_init_net(struct net *net) if (err < 0) goto err_assign; + sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", + ipip6_tunnel_setup); + if (!sitn->fb_tunnel_dev) { + err = -ENOMEM; + goto err_alloc_dev; + } + + sitn->fb_tunnel_dev->init = ipip6_fb_tunnel_init; + dev_net_set(sitn->fb_tunnel_dev, net); + + if ((err = register_netdev(sitn->fb_tunnel_dev))) + goto err_reg_dev; + return 0; +err_reg_dev: + free_netdev(sitn->fb_tunnel_dev); +err_alloc_dev: + /* nothing */ err_assign: kfree(sitn); err_alloc: @@ -1112,6 +1128,9 @@ static void sit_exit_net(struct net *net) struct sit_net *sitn; sitn = net_generic(net, sit_net_id); + rtnl_lock(); + unregister_netdevice(sitn->fb_tunnel_dev); + rtnl_unlock(); kfree(sitn); } @@ -1126,7 +1145,6 @@ static void __exit sit_cleanup(void) rtnl_lock(); sit_destroy_tunnels(); - unregister_netdevice(ipip6_fb_tunnel_dev); rtnl_unlock(); unregister_pernet_gen_device(sit_net_id, &sit_net_ops); @@ -1143,32 +1161,11 @@ static int __init sit_init(void) return -EAGAIN; } - ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", - ipip6_tunnel_setup); - if (!ipip6_fb_tunnel_dev) { - err = -ENOMEM; - goto err1; - } - - ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; - - if ((err = register_netdev(ipip6_fb_tunnel_dev))) - goto err2; - err = register_pernet_gen_device(&sit_net_id, &sit_net_ops); if (err < 0) - goto err3; + xfrm4_tunnel_deregister(&sit_handler, AF_INET6); - out: return err; - err2: - free_netdev(ipip6_fb_tunnel_dev); - err1: - xfrm4_tunnel_deregister(&sit_handler, AF_INET6); - goto out; -err3: - unregister_netdevice(ipip6_fb_tunnel_dev); - goto err1; } module_init(sit_init); -- cgit v1.2.3 From 291821766b5ca90ffe3fb64531d49537c4ff7395 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:16:38 -0700 Subject: [SIT]: Make tunnels hashes per-net. Just move all the hashes on the sit_net structure and patch the rest of the code appropriately. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index d0c1f2db7f2..f82494bc4c5 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -70,15 +70,15 @@ static void ipip6_tunnel_setup(struct net_device *dev); static int sit_net_id; struct sit_net { + struct ip_tunnel *tunnels_r_l[HASH_SIZE]; + struct ip_tunnel *tunnels_r[HASH_SIZE]; + struct ip_tunnel *tunnels_l[HASH_SIZE]; + struct ip_tunnel *tunnels_wc[1]; + struct ip_tunnel **tunnels[4]; + struct net_device *fb_tunnel_dev; }; -static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; -static struct ip_tunnel *tunnels_r[HASH_SIZE]; -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 DEFINE_RWLOCK(ipip6_lock); static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, @@ -87,21 +87,22 @@ static struct ip_tunnel * ipip6_tunnel_lookup(struct net *net, unsigned h0 = HASH(remote); unsigned h1 = HASH(local); struct ip_tunnel *t; + struct sit_net *sitn = net_generic(net, sit_net_id); - for (t = tunnels_r_l[h0^h1]; t; t = t->next) { + for (t = sitn->tunnels_r_l[h0^h1]; t; t = t->next) { if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) return t; } - for (t = tunnels_r[h0]; t; t = t->next) { + for (t = sitn->tunnels_r[h0]; t; t = t->next) { if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP)) return t; } - for (t = tunnels_l[h1]; t; t = t->next) { + for (t = sitn->tunnels_l[h1]; t; t = t->next) { if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP)) return t; } - if ((t = tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) + if ((t = sitn->tunnels_wc[0]) != NULL && (t->dev->flags&IFF_UP)) return t; return NULL; } @@ -122,7 +123,7 @@ static struct ip_tunnel **__ipip6_bucket(struct sit_net *sitn, prio |= 1; h ^= HASH(local); } - return &tunnels[prio][h]; + return &sitn->tunnels[prio][h]; } static inline struct ip_tunnel **ipip6_bucket(struct sit_net *sitn, @@ -387,7 +388,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) if (dev == sitn->fb_tunnel_dev) { write_lock_bh(&ipip6_lock); - tunnels_wc[0] = NULL; + sitn->tunnels_wc[0] = NULL; write_unlock_bh(&ipip6_lock); dev_put(dev); } else { @@ -1050,6 +1051,8 @@ static int ipip6_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = netdev_priv(dev); struct iphdr *iph = &tunnel->parms.iph; + struct net *net = dev_net(dev); + struct sit_net *sitn = net_generic(net, sit_net_id); tunnel->dev = dev; strcpy(tunnel->parms.name, dev->name); @@ -1060,7 +1063,7 @@ static int ipip6_fb_tunnel_init(struct net_device *dev) iph->ttl = 64; dev_hold(dev); - tunnels_wc[0] = tunnel; + sitn->tunnels_wc[0] = tunnel; return 0; } @@ -1070,7 +1073,7 @@ static struct xfrm_tunnel sit_handler = { .priority = 1, }; -static void __exit sit_destroy_tunnels(void) +static void sit_destroy_tunnels(struct sit_net *sitn) { int prio; @@ -1078,7 +1081,7 @@ static void __exit sit_destroy_tunnels(void) int h; for (h = 0; h < HASH_SIZE; h++) { struct ip_tunnel *t; - while ((t = tunnels[prio][h]) != NULL) + while ((t = sitn->tunnels[prio][h]) != NULL) unregister_netdevice(t->dev); } } @@ -1090,7 +1093,7 @@ static int sit_init_net(struct net *net) struct sit_net *sitn; err = -ENOMEM; - sitn = kmalloc(sizeof(struct sit_net), GFP_KERNEL); + sitn = kzalloc(sizeof(struct sit_net), GFP_KERNEL); if (sitn == NULL) goto err_alloc; @@ -1098,6 +1101,11 @@ static int sit_init_net(struct net *net) if (err < 0) goto err_assign; + sitn->tunnels[0] = sitn->tunnels_wc; + sitn->tunnels[1] = sitn->tunnels_l; + sitn->tunnels[2] = sitn->tunnels_r; + sitn->tunnels[3] = sitn->tunnels_r_l; + sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", ipip6_tunnel_setup); if (!sitn->fb_tunnel_dev) { @@ -1129,6 +1137,7 @@ static void sit_exit_net(struct net *net) sitn = net_generic(net, sit_net_id); rtnl_lock(); + sit_destroy_tunnels(sitn); unregister_netdevice(sitn->fb_tunnel_dev); rtnl_unlock(); kfree(sitn); @@ -1143,10 +1152,6 @@ static void __exit sit_cleanup(void) { xfrm4_tunnel_deregister(&sit_handler, AF_INET6); - rtnl_lock(); - sit_destroy_tunnels(); - rtnl_unlock(); - unregister_pernet_gen_device(sit_net_id, &sit_net_ops); } -- cgit v1.2.3 From 907a08c4023b54ffebf3fb966efcbcc1312abe32 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:16:58 -0700 Subject: [SIT]: Use proper net in routing calls. I.e. replace init_net stubs in ip_route_output_key() calls. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index f82494bc4c5..7badac6c741 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -527,11 +527,12 @@ out: skb_reset_network_header(skb2); /* Try to guess incoming interface */ - rt6i = rt6_lookup(&init_net, &iph6->saddr, NULL, NULL, 0); + rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0); if (rt6i && rt6i->rt6i_dev) { skb2->dev = rt6i->rt6i_dev; - rt6i = rt6_lookup(&init_net, &iph6->daddr, &iph6->saddr, NULL, 0); + rt6i = rt6_lookup(dev_net(skb->dev), + &iph6->daddr, &iph6->saddr, NULL, 0); if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); @@ -701,7 +702,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) .tos = RT_TOS(tos) } }, .oif = tunnel->parms.link, .proto = IPPROTO_IPV6 }; - if (ip_route_output_key(&init_net, &rt, &fl)) { + if (ip_route_output_key(dev_net(dev), &rt, &fl)) { tunnel->stat.tx_carrier_errors++; goto tx_error_icmp; } @@ -830,7 +831,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) .oif = tunnel->parms.link, .proto = IPPROTO_IPV6 }; struct rtable *rt; - if (!ip_route_output_key(&init_net, &rt, &fl)) { + if (!ip_route_output_key(dev_net(dev), &rt, &fl)) { tdev = rt->u.dst.dev; ip_rt_put(rt); } @@ -838,7 +839,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) } if (!tdev && tunnel->parms.link) - tdev = __dev_get_by_index(&init_net, tunnel->parms.link); + tdev = __dev_get_by_index(dev_net(dev), tunnel->parms.link); if (tdev) { dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); -- cgit v1.2.3 From 7a97146cc6e8145f65abfee36e56de7b8061c34f Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 16 Apr 2008 01:17:18 -0700 Subject: [SIT]: Allow to create SIT tunnels in net namespaces. Set proper net and mark a new device as NETNS_LOCAL before registering. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/ipv6/sit.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/ipv6/sit.c') diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 7badac6c741..4b2f1033994 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -182,6 +182,8 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct net *net, if (dev == NULL) return NULL; + dev_net_set(dev, net); + if (strchr(name, '%')) { if (dev_alloc_name(dev, name) < 0) goto failed_free; @@ -1029,6 +1031,7 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; + dev->features |= NETIF_F_NETNS_LOCAL; } static int ipip6_tunnel_init(struct net_device *dev) -- cgit v1.2.3