#include "ipv6.h"
#include "feat.h"
-/* Socket used for sending RSTs and ACKs */
-static struct socket *dccp_v6_ctl_socket;
+/* The per-net dccp.v6_ctl_sk is used for sending RSTs and ACKs */
static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
int err;
__u64 seq;
- sk = inet6_lookup(&init_net, &dccp_hashinfo, &hdr->daddr, dh->dccph_dport,
+ sk = inet6_lookup(dev_net(skb->dev), &dccp_hashinfo,
+ &hdr->daddr, dh->dccph_dport,
&hdr->saddr, dh->dccph_sport, inet6_iif(skb));
if (sk == NULL) {
struct ipv6hdr *rxip6h;
struct sk_buff *skb;
struct flowi fl;
+ struct net *net = dev_net(rxskb->dst->dev);
+ struct sock *ctl_sk = net->dccp.v6_ctl_sk;
if (dccp_hdr(rxskb)->dccph_type == DCCP_PKT_RESET)
return;
if (!ipv6_unicast_destination(rxskb))
return;
- skb = dccp_ctl_make_reset(dccp_v6_ctl_socket, rxskb);
+ skb = dccp_ctl_make_reset(ctl_sk, rxskb);
if (skb == NULL)
return;
security_skb_classify_flow(rxskb, &fl);
/* sk = NULL, but it is safe for now. RST socket required. */
- if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
+ if (!ip6_dst_lookup(ctl_sk, &skb->dst, &fl)) {
if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
+ ip6_xmit(ctl_sk, skb, &fl, NULL, 0);
DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
return;
if (req != NULL)
return dccp_check_req(sk, skb, req, prev);
- nsk = __inet6_lookup_established(&init_net, &dccp_hashinfo,
+ nsk = __inet6_lookup_established(sock_net(sk), &dccp_hashinfo,
&iph->saddr, dh->dccph_sport,
&iph->daddr, ntohs(dh->dccph_dport),
inet6_iif(skb));
ireq6 = inet6_rsk(req);
ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr);
ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr);
- ireq6->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
__inet6_hash(newsk);
- inet_inherit_port(sk, newsk);
+ __inet_inherit_port(sk, newsk);
return newsk;
/* Step 2:
* Look up flow ID in table and get corresponding socket */
- sk = __inet6_lookup(&init_net, &dccp_hashinfo, &ipv6_hdr(skb)->saddr,
- dh->dccph_sport,
+ sk = __inet6_lookup(dev_net(skb->dst->dev), &dccp_hashinfo,
+ &ipv6_hdr(skb)->saddr, dh->dccph_sport,
&ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
inet6_iif(skb));
/*
return err;
}
-static int dccp_v6_destroy_sock(struct sock *sk)
+static void dccp_v6_destroy_sock(struct sock *sk)
{
dccp_destroy_sock(sk);
- return inet6_destroy_sock(sk);
+ inet6_destroy_sock(sk);
}
static struct timewait_sock_ops dccp6_timewait_sock_ops = {
.twsk_obj_size = sizeof(struct dccp6_timewait_sock),
};
-DEFINE_PROTO_INUSE(dccp_v6)
-
static struct proto dccp_v6_prot = {
.name = "DCCPv6",
.owner = THIS_MODULE,
.compat_setsockopt = compat_dccp_setsockopt,
.compat_getsockopt = compat_dccp_getsockopt,
#endif
- REF_PROTO_INUSE(dccp_v6)
};
static struct inet6_protocol dccp_v6_protocol = {
.flags = INET_PROTOSW_ICSK,
};
+static int dccp_v6_init_net(struct net *net)
+{
+ int err;
+
+ err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
+ SOCK_DCCP, IPPROTO_DCCP, net);
+ return err;
+}
+
+static void dccp_v6_exit_net(struct net *net)
+{
+ inet_ctl_sock_destroy(net->dccp.v6_ctl_sk);
+}
+
+static struct pernet_operations dccp_v6_ops = {
+ .init = dccp_v6_init_net,
+ .exit = dccp_v6_exit_net,
+};
+
static int __init dccp_v6_init(void)
{
int err = proto_register(&dccp_v6_prot, 1);
inet6_register_protosw(&dccp_v6_protosw);
- err = inet_csk_ctl_sock_create(&dccp_v6_ctl_socket, PF_INET6,
- SOCK_DCCP, IPPROTO_DCCP);
+ err = register_pernet_subsys(&dccp_v6_ops);
if (err != 0)
- goto out_unregister_protosw;
+ goto out_destroy_ctl_sock;
out:
return err;
-out_unregister_protosw:
+
+out_destroy_ctl_sock:
inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
inet6_unregister_protosw(&dccp_v6_protosw);
out_unregister_proto:
static void __exit dccp_v6_exit(void)
{
+ unregister_pernet_subsys(&dccp_v6_ops);
inet6_del_protocol(&dccp_v6_protocol, IPPROTO_DCCP);
inet6_unregister_protosw(&dccp_v6_protosw);
proto_unregister(&dccp_v6_prot);