#include <linux/seq_file.h>
static struct raw_hashinfo raw_v6_hashinfo = {
- .lock = __RW_LOCK_UNLOCKED(),
+ .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock),
};
-static void raw_v6_hash(struct sock *sk)
-{
- raw_hash_sk(sk, &raw_v6_hashinfo);
-}
-
-static void raw_v6_unhash(struct sock *sk)
-{
- raw_unhash_sk(sk, &raw_v6_hashinfo);
-}
-
-
-static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
- struct in6_addr *loc_addr, struct in6_addr *rmt_addr, int dif)
+static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk,
+ unsigned short num, struct in6_addr *loc_addr,
+ struct in6_addr *rmt_addr, int dif)
{
struct hlist_node *node;
int is_multicast = ipv6_addr_is_multicast(loc_addr);
if (inet_sk(sk)->num == num) {
struct ipv6_pinfo *np = inet6_sk(sk);
+ if (!net_eq(sock_net(sk), net))
+ continue;
+
if (!ipv6_addr_any(&np->daddr) &&
!ipv6_addr_equal(&np->daddr, rmt_addr))
continue;
struct sock *sk;
int delivered = 0;
__u8 hash;
+ struct net *net;
saddr = &ipv6_hdr(skb)->saddr;
daddr = saddr + 1;
read_lock(&raw_v6_hashinfo.lock);
sk = sk_head(&raw_v6_hashinfo.ht[hash]);
- /*
- * The first socket found will be delivered after
- * delivery to transport protocols.
- */
-
if (sk == NULL)
goto out;
- sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
+ net = dev_net(skb->dev);
+ sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif);
while (sk) {
int filtered;
rawv6_rcv(sk, clone);
}
}
- sk = __raw_v6_lookup(sk_next(sk), nexthdr, daddr, saddr,
+ sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr,
IP6CB(skb)->iif);
}
out:
if (!sk->sk_bound_dev_if)
goto out;
- dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
+ dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if);
if (!dev) {
err = -ENODEV;
goto out;
v4addr = LOOPBACK4_IPV6;
if (!(addr_type & IPV6_ADDR_MULTICAST)) {
err = -EADDRNOTAVAIL;
- if (!ipv6_chk_addr(&init_net, &addr->sin6_addr,
+ if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr,
dev, 0)) {
if (dev)
dev_put(dev);
struct sock *sk;
int hash;
struct in6_addr *saddr, *daddr;
+ struct net *net;
hash = nexthdr & (RAW_HTABLE_SIZE - 1);
if (sk != NULL) {
saddr = &ipv6_hdr(skb)->saddr;
daddr = &ipv6_hdr(skb)->daddr;
+ net = dev_net(skb->dev);
- while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr,
+ while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr,
IP6CB(skb)->iif))) {
rawv6_err(sk, skb, NULL, type, code,
inner_offset, info);
skb_reserve(skb, hh_len);
skb->priority = sk->sk_priority;
+ skb->mark = sk->sk_mark;
skb->dst = dst_clone(&rt->u.dst);
skb_put(skb, length);
*/
memset(&fl, 0, sizeof(fl));
+ fl.mark = sk->sk_mark;
+
if (sin6) {
if (addr_len < SIN6_LEN_RFC2133)
return -EINVAL;
else
hlimit = np->hop_limit;
if (hlimit < 0)
- hlimit = dst_metric(dst, RTAX_HOPLIMIT);
- if (hlimit < 0)
- hlimit = ipv6_get_hoplimit(dst->dev);
+ hlimit = ip6_dst_hoplimit(dst);
}
if (tclass < 0) {
return(0);
}
-DEFINE_PROTO_INUSE(rawv6)
-
struct proto rawv6_prot = {
.name = "RAWv6",
.owner = THIS_MODULE,
.recvmsg = rawv6_recvmsg,
.bind = rawv6_bind,
.backlog_rcv = rawv6_rcv_skb,
- .hash = raw_v6_hash,
- .unhash = raw_v6_unhash,
+ .hash = raw_hash_sk,
+ .unhash = raw_unhash_sk,
.obj_size = sizeof(struct raw6_sock),
+ .h.raw_hash = &raw_v6_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_rawv6_setsockopt,
.compat_getsockopt = compat_rawv6_getsockopt,
#endif
- REF_PROTO_INUSE(rawv6)
};
#ifdef CONFIG_PROC_FS
static int raw6_seq_open(struct inode *inode, struct file *file)
{
- return raw_seq_open(file, &raw_v6_hashinfo, PF_INET6);
+ return raw_seq_open(inode, file, &raw_v6_hashinfo, &raw6_seq_ops);
}
static const struct file_operations raw6_seq_fops = {
.open = raw6_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release_private,
+ .release = seq_release_net,
};
-int __init raw6_proc_init(void)
+static int raw6_init_net(struct net *net)
{
- if (!proc_net_fops_create(&init_net, "raw6", S_IRUGO, &raw6_seq_fops))
+ if (!proc_net_fops_create(net, "raw6", S_IRUGO, &raw6_seq_fops))
return -ENOMEM;
+
return 0;
}
+static void raw6_exit_net(struct net *net)
+{
+ proc_net_remove(net, "raw6");
+}
+
+static struct pernet_operations raw6_net_ops = {
+ .init = raw6_init_net,
+ .exit = raw6_exit_net,
+};
+
+int __init raw6_proc_init(void)
+{
+ return register_pernet_subsys(&raw6_net_ops);
+}
+
void raw6_proc_exit(void)
{
- proc_net_remove(&init_net, "raw6");
+ unregister_pernet_subsys(&raw6_net_ops);
}
#endif /* CONFIG_PROC_FS */