#include <net/dsfield.h>
#include <net/timewait_sock.h>
#include <net/netdma.h>
+#include <net/inet_common.h>
#include <asm/uaccess.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
-/* Socket used for sending RSTs and ACKs */
-static struct socket *tcp6_socket;
-
static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
static void tcp_v6_send_check(struct sock *sk, int len,
struct tcp_sock *tp;
__u32 seq;
- sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr,
+ sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr,
th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
if (sk == NULL) {
return NULL;
for (i = 0; i < tp->md5sig_info->entries6; i++) {
- if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0)
+ if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr))
return &tp->md5sig_info->keys6[i].base;
}
return NULL;
int i;
for (i = 0; i < tp->md5sig_info->entries6; i++) {
- if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) {
+ if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) {
/* Free the key */
kfree(tp->md5sig_info->keys6[i].base.key);
tp->md5sig_info->entries6--;
hp = tcp_get_md5sig_pool();
if (!hp) {
- printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__);
+ printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
goto clear_hash_noput;
}
bp = &hp->md5_blk.ip6;
/* Now store the hash into the packet */
err = crypto_hash_init(desc);
if (err) {
- printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__);
+ printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
goto clear_hash;
}
err = crypto_hash_update(desc, sg, nbytes);
if (err) {
- printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__);
+ printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
goto clear_hash;
}
err = crypto_hash_final(desc, md5_hash);
if (err) {
- printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__);
+ printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
goto clear_hash;
}
struct tcphdr *th = tcp_hdr(skb), *t1;
struct sk_buff *buff;
struct flowi fl;
+ struct net *net = dev_net(skb->dst->dev);
+ struct sock *ctl_sk = net->ipv6.tcp_sk;
unsigned int tot_len = sizeof(*th);
#ifdef CONFIG_TCP_MD5SIG
struct tcp_md5sig_key *key;
fl.fl_ip_sport = t1->source;
security_skb_classify_flow(skb, &fl);
- /* sk = NULL, but it is safe for now. RST socket required. */
- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+ /* Pass a socket to ip6_dst_lookup either it is for RST
+ * Underlying function will use this to retrieve the network
+ * namespace
+ */
+ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
+ ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
return;
struct tcphdr *th = tcp_hdr(skb), *t1;
struct sk_buff *buff;
struct flowi fl;
+ struct net *net = dev_net(skb->dev);
+ struct sock *ctl_sk = net->ipv6.tcp_sk;
unsigned int tot_len = sizeof(struct tcphdr);
__be32 *topt;
#ifdef CONFIG_TCP_MD5SIG
fl.fl_ip_sport = t1->source;
security_skb_classify_flow(skb, &fl);
- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+ if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) {
if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) {
- ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0);
+ ip6_xmit(ctl_sk, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
return;
}
if (req)
return tcp_check_req(sk, skb, req, prev);
- nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo,
+ nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
&ipv6_hdr(skb)->saddr, th->source,
&ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
tcp_parse_options(skb, &tmp_opt, 0);
- if (want_cookie) {
+ if (want_cookie && !tmp_opt.saw_tstamp)
tcp_clear_options(&tmp_opt);
- tmp_opt.saw_tstamp = 0;
- }
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
tcp_openreq_init(req, &tmp_opt, skb);
if (want_cookie) {
isn = cookie_v6_init_sequence(sk, skb, &req->mss);
+ req->cookie_ts = tmp_opt.tstamp_ok;
} else if (!isn) {
if (ipv6_opt_accepted(sk, skb) ||
np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
#endif
__inet6_hash(newsk);
- inet_inherit_port(sk, newsk);
+ __inet_inherit_port(sk, newsk);
return newsk;
TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
TCP_SKB_CB(skb)->sacked = 0;
- sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo,
+ sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo,
&ipv6_hdr(skb)->saddr, th->source,
&ipv6_hdr(skb)->daddr, ntohs(th->dest),
inet6_iif(skb));
{
struct sock *sk2;
- sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo,
+ sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
&ipv6_hdr(skb)->daddr,
ntohs(th->dest), inet6_iif(skb));
if (sk2 != NULL) {
return 0;
}
-static struct file_operations tcp6_seq_fops;
static struct tcp_seq_afinfo tcp6_seq_afinfo = {
- .owner = THIS_MODULE,
.name = "tcp6",
.family = AF_INET6,
- .seq_show = tcp6_seq_show,
- .seq_fops = &tcp6_seq_fops,
+ .seq_fops = {
+ .owner = THIS_MODULE,
+ },
+ .seq_ops = {
+ .show = tcp6_seq_show,
+ },
};
-int __init tcp6_proc_init(void)
+int tcp6_proc_init(struct net *net)
{
- return tcp_proc_register(&tcp6_seq_afinfo);
+ return tcp_proc_register(net, &tcp6_seq_afinfo);
}
-void tcp6_proc_exit(void)
+void tcp6_proc_exit(struct net *net)
{
- tcp_proc_unregister(&tcp6_seq_afinfo);
+ tcp_proc_unregister(net, &tcp6_seq_afinfo);
}
#endif
-DEFINE_PROTO_INUSE(tcpv6)
-
struct proto tcpv6_prot = {
.name = "TCPv6",
.owner = THIS_MODULE,
.obj_size = sizeof(struct tcp6_sock),
.twsk_prot = &tcp6_timewait_sock_ops,
.rsk_prot = &tcp6_request_sock_ops,
- .hashinfo = &tcp_hashinfo,
+ .h.hashinfo = &tcp_hashinfo,
#ifdef CONFIG_COMPAT
.compat_setsockopt = compat_tcp_setsockopt,
.compat_getsockopt = compat_tcp_getsockopt,
#endif
- REF_PROTO_INUSE(tcpv6)
};
static struct inet6_protocol tcpv6_protocol = {
INET_PROTOSW_ICSK,
};
+static int tcpv6_net_init(struct net *net)
+{
+ return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
+ SOCK_RAW, IPPROTO_TCP, net);
+}
+
+static void tcpv6_net_exit(struct net *net)
+{
+ inet_ctl_sock_destroy(net->ipv6.tcp_sk);
+}
+
+static struct pernet_operations tcpv6_net_ops = {
+ .init = tcpv6_net_init,
+ .exit = tcpv6_net_exit,
+};
+
int __init tcpv6_init(void)
{
int ret;
if (ret)
goto out_tcpv6_protocol;
- ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6,
- SOCK_RAW, IPPROTO_TCP);
+ ret = register_pernet_subsys(&tcpv6_net_ops);
if (ret)
goto out_tcpv6_protosw;
out:
void tcpv6_exit(void)
{
- sock_release(tcp6_socket);
+ unregister_pernet_subsys(&tcpv6_net_ops);
inet6_unregister_protosw(&tcpv6_protosw);
inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
}