diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 199 |
1 files changed, 124 insertions, 75 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 12750f2b05ab..715965f0fac0 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <net/dsfield.h> | 60 | #include <net/dsfield.h> |
61 | #include <net/timewait_sock.h> | 61 | #include <net/timewait_sock.h> |
62 | #include <net/netdma.h> | 62 | #include <net/netdma.h> |
63 | #include <net/inet_common.h> | ||
63 | 64 | ||
64 | #include <asm/uaccess.h> | 65 | #include <asm/uaccess.h> |
65 | 66 | ||
@@ -69,9 +70,6 @@ | |||
69 | #include <linux/crypto.h> | 70 | #include <linux/crypto.h> |
70 | #include <linux/scatterlist.h> | 71 | #include <linux/scatterlist.h> |
71 | 72 | ||
72 | /* Socket used for sending RSTs and ACKs */ | ||
73 | static struct socket *tcp6_socket; | ||
74 | |||
75 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); | 73 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
76 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); | 74 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); |
77 | static void tcp_v6_send_check(struct sock *sk, int len, | 75 | static void tcp_v6_send_check(struct sock *sk, int len, |
@@ -324,7 +322,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
324 | struct tcp_sock *tp; | 322 | struct tcp_sock *tp; |
325 | __u32 seq; | 323 | __u32 seq; |
326 | 324 | ||
327 | sk = inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, &hdr->daddr, | 325 | sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr, |
328 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 326 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); |
329 | 327 | ||
330 | if (sk == NULL) { | 328 | if (sk == NULL) { |
@@ -455,8 +453,7 @@ out: | |||
455 | } | 453 | } |
456 | 454 | ||
457 | 455 | ||
458 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | 456 | static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req) |
459 | struct dst_entry *dst) | ||
460 | { | 457 | { |
461 | struct inet6_request_sock *treq = inet6_rsk(req); | 458 | struct inet6_request_sock *treq = inet6_rsk(req); |
462 | struct ipv6_pinfo *np = inet6_sk(sk); | 459 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -464,6 +461,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
464 | struct ipv6_txoptions *opt = NULL; | 461 | struct ipv6_txoptions *opt = NULL; |
465 | struct in6_addr * final_p = NULL, final; | 462 | struct in6_addr * final_p = NULL, final; |
466 | struct flowi fl; | 463 | struct flowi fl; |
464 | struct dst_entry *dst; | ||
467 | int err = -1; | 465 | int err = -1; |
468 | 466 | ||
469 | memset(&fl, 0, sizeof(fl)); | 467 | memset(&fl, 0, sizeof(fl)); |
@@ -476,24 +474,22 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
476 | fl.fl_ip_sport = inet_sk(sk)->sport; | 474 | fl.fl_ip_sport = inet_sk(sk)->sport; |
477 | security_req_classify_flow(req, &fl); | 475 | security_req_classify_flow(req, &fl); |
478 | 476 | ||
479 | if (dst == NULL) { | 477 | opt = np->opt; |
480 | opt = np->opt; | 478 | if (opt && opt->srcrt) { |
481 | if (opt && opt->srcrt) { | 479 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; |
482 | struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt; | 480 | ipv6_addr_copy(&final, &fl.fl6_dst); |
483 | ipv6_addr_copy(&final, &fl.fl6_dst); | 481 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); |
484 | ipv6_addr_copy(&fl.fl6_dst, rt0->addr); | 482 | final_p = &final; |
485 | final_p = &final; | ||
486 | } | ||
487 | |||
488 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
489 | if (err) | ||
490 | goto done; | ||
491 | if (final_p) | ||
492 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
493 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
494 | goto done; | ||
495 | } | 483 | } |
496 | 484 | ||
485 | err = ip6_dst_lookup(sk, &dst, &fl); | ||
486 | if (err) | ||
487 | goto done; | ||
488 | if (final_p) | ||
489 | ipv6_addr_copy(&fl.fl6_dst, final_p); | ||
490 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | ||
491 | goto done; | ||
492 | |||
497 | skb = tcp_make_synack(sk, dst, req); | 493 | skb = tcp_make_synack(sk, dst, req); |
498 | if (skb) { | 494 | if (skb) { |
499 | struct tcphdr *th = tcp_hdr(skb); | 495 | struct tcphdr *th = tcp_hdr(skb); |
@@ -514,6 +510,20 @@ done: | |||
514 | return err; | 510 | return err; |
515 | } | 511 | } |
516 | 512 | ||
513 | static inline void syn_flood_warning(struct sk_buff *skb) | ||
514 | { | ||
515 | #ifdef CONFIG_SYN_COOKIES | ||
516 | if (sysctl_tcp_syncookies) | ||
517 | printk(KERN_INFO | ||
518 | "TCPv6: Possible SYN flooding on port %d. " | ||
519 | "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest)); | ||
520 | else | ||
521 | #endif | ||
522 | printk(KERN_INFO | ||
523 | "TCPv6: Possible SYN flooding on port %d. " | ||
524 | "Dropping request.\n", ntohs(tcp_hdr(skb)->dest)); | ||
525 | } | ||
526 | |||
517 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 527 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
518 | { | 528 | { |
519 | if (inet6_rsk(req)->pktopts) | 529 | if (inet6_rsk(req)->pktopts) |
@@ -533,7 +543,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
533 | return NULL; | 543 | return NULL; |
534 | 544 | ||
535 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 545 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
536 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) | 546 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr)) |
537 | return &tp->md5sig_info->keys6[i].base; | 547 | return &tp->md5sig_info->keys6[i].base; |
538 | } | 548 | } |
539 | return NULL; | 549 | return NULL; |
@@ -622,7 +632,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | |||
622 | int i; | 632 | int i; |
623 | 633 | ||
624 | for (i = 0; i < tp->md5sig_info->entries6; i++) { | 634 | for (i = 0; i < tp->md5sig_info->entries6; i++) { |
625 | if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { | 635 | if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) { |
626 | /* Free the key */ | 636 | /* Free the key */ |
627 | kfree(tp->md5sig_info->keys6[i].base.key); | 637 | kfree(tp->md5sig_info->keys6[i].base.key); |
628 | tp->md5sig_info->entries6--; | 638 | tp->md5sig_info->entries6--; |
@@ -741,7 +751,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
741 | 751 | ||
742 | hp = tcp_get_md5sig_pool(); | 752 | hp = tcp_get_md5sig_pool(); |
743 | if (!hp) { | 753 | if (!hp) { |
744 | printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); | 754 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); |
745 | goto clear_hash_noput; | 755 | goto clear_hash_noput; |
746 | } | 756 | } |
747 | bp = &hp->md5_blk.ip6; | 757 | bp = &hp->md5_blk.ip6; |
@@ -781,17 +791,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | |||
781 | /* Now store the hash into the packet */ | 791 | /* Now store the hash into the packet */ |
782 | err = crypto_hash_init(desc); | 792 | err = crypto_hash_init(desc); |
783 | if (err) { | 793 | if (err) { |
784 | printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); | 794 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); |
785 | goto clear_hash; | 795 | goto clear_hash; |
786 | } | 796 | } |
787 | err = crypto_hash_update(desc, sg, nbytes); | 797 | err = crypto_hash_update(desc, sg, nbytes); |
788 | if (err) { | 798 | if (err) { |
789 | printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); | 799 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); |
790 | goto clear_hash; | 800 | goto clear_hash; |
791 | } | 801 | } |
792 | err = crypto_hash_final(desc, md5_hash); | 802 | err = crypto_hash_final(desc, md5_hash); |
793 | if (err) { | 803 | if (err) { |
794 | printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); | 804 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); |
795 | goto clear_hash; | 805 | goto clear_hash; |
796 | } | 806 | } |
797 | 807 | ||
@@ -917,7 +927,7 @@ done_opts: | |||
917 | } | 927 | } |
918 | #endif | 928 | #endif |
919 | 929 | ||
920 | static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 930 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
921 | .family = AF_INET6, | 931 | .family = AF_INET6, |
922 | .obj_size = sizeof(struct tcp6_request_sock), | 932 | .obj_size = sizeof(struct tcp6_request_sock), |
923 | .rtx_syn_ack = tcp_v6_send_synack, | 933 | .rtx_syn_ack = tcp_v6_send_synack, |
@@ -979,6 +989,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
979 | struct tcphdr *th = tcp_hdr(skb), *t1; | 989 | struct tcphdr *th = tcp_hdr(skb), *t1; |
980 | struct sk_buff *buff; | 990 | struct sk_buff *buff; |
981 | struct flowi fl; | 991 | struct flowi fl; |
992 | struct net *net = dev_net(skb->dst->dev); | ||
993 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
982 | unsigned int tot_len = sizeof(*th); | 994 | unsigned int tot_len = sizeof(*th); |
983 | #ifdef CONFIG_TCP_MD5SIG | 995 | #ifdef CONFIG_TCP_MD5SIG |
984 | struct tcp_md5sig_key *key; | 996 | struct tcp_md5sig_key *key; |
@@ -1059,11 +1071,14 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1059 | fl.fl_ip_sport = t1->source; | 1071 | fl.fl_ip_sport = t1->source; |
1060 | security_skb_classify_flow(skb, &fl); | 1072 | security_skb_classify_flow(skb, &fl); |
1061 | 1073 | ||
1062 | /* sk = NULL, but it is safe for now. RST socket required. */ | 1074 | /* Pass a socket to ip6_dst_lookup either it is for RST |
1063 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1075 | * Underlying function will use this to retrieve the network |
1076 | * namespace | ||
1077 | */ | ||
1078 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | ||
1064 | 1079 | ||
1065 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1080 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1066 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1081 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1067 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1082 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1068 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 1083 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); |
1069 | return; | 1084 | return; |
@@ -1079,6 +1094,8 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1079 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1094 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1080 | struct sk_buff *buff; | 1095 | struct sk_buff *buff; |
1081 | struct flowi fl; | 1096 | struct flowi fl; |
1097 | struct net *net = dev_net(skb->dev); | ||
1098 | struct sock *ctl_sk = net->ipv6.tcp_sk; | ||
1082 | unsigned int tot_len = sizeof(struct tcphdr); | 1099 | unsigned int tot_len = sizeof(struct tcphdr); |
1083 | __be32 *topt; | 1100 | __be32 *topt; |
1084 | #ifdef CONFIG_TCP_MD5SIG | 1101 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1160,9 +1177,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1160 | fl.fl_ip_sport = t1->source; | 1177 | fl.fl_ip_sport = t1->source; |
1161 | security_skb_classify_flow(skb, &fl); | 1178 | security_skb_classify_flow(skb, &fl); |
1162 | 1179 | ||
1163 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1180 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { |
1164 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1181 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1165 | ip6_xmit(tcp6_socket->sk, buff, &fl, NULL, 0); | 1182 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1166 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1183 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1167 | return; | 1184 | return; |
1168 | } | 1185 | } |
@@ -1202,7 +1219,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1202 | if (req) | 1219 | if (req) |
1203 | return tcp_check_req(sk, skb, req, prev); | 1220 | return tcp_check_req(sk, skb, req, prev); |
1204 | 1221 | ||
1205 | nsk = __inet6_lookup_established(sk->sk_net, &tcp_hashinfo, | 1222 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
1206 | &ipv6_hdr(skb)->saddr, th->source, | 1223 | &ipv6_hdr(skb)->saddr, th->source, |
1207 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); | 1224 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb)); |
1208 | 1225 | ||
@@ -1215,9 +1232,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
1215 | return NULL; | 1232 | return NULL; |
1216 | } | 1233 | } |
1217 | 1234 | ||
1218 | #if 0 /*def CONFIG_SYN_COOKIES*/ | 1235 | #ifdef CONFIG_SYN_COOKIES |
1219 | if (!th->rst && !th->syn && th->ack) | 1236 | if (!th->rst && !th->syn && th->ack) |
1220 | sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt)); | 1237 | sk = cookie_v6_check(sk, skb); |
1221 | #endif | 1238 | #endif |
1222 | return sk; | 1239 | return sk; |
1223 | } | 1240 | } |
@@ -1233,6 +1250,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1233 | struct tcp_sock *tp = tcp_sk(sk); | 1250 | struct tcp_sock *tp = tcp_sk(sk); |
1234 | struct request_sock *req = NULL; | 1251 | struct request_sock *req = NULL; |
1235 | __u32 isn = TCP_SKB_CB(skb)->when; | 1252 | __u32 isn = TCP_SKB_CB(skb)->when; |
1253 | #ifdef CONFIG_SYN_COOKIES | ||
1254 | int want_cookie = 0; | ||
1255 | #else | ||
1256 | #define want_cookie 0 | ||
1257 | #endif | ||
1236 | 1258 | ||
1237 | if (skb->protocol == htons(ETH_P_IP)) | 1259 | if (skb->protocol == htons(ETH_P_IP)) |
1238 | return tcp_v4_conn_request(sk, skb); | 1260 | return tcp_v4_conn_request(sk, skb); |
@@ -1240,12 +1262,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1240 | if (!ipv6_unicast_destination(skb)) | 1262 | if (!ipv6_unicast_destination(skb)) |
1241 | goto drop; | 1263 | goto drop; |
1242 | 1264 | ||
1243 | /* | ||
1244 | * There are no SYN attacks on IPv6, yet... | ||
1245 | */ | ||
1246 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1265 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
1247 | if (net_ratelimit()) | 1266 | if (net_ratelimit()) |
1248 | printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n"); | 1267 | syn_flood_warning(skb); |
1268 | #ifdef CONFIG_SYN_COOKIES | ||
1269 | if (sysctl_tcp_syncookies) | ||
1270 | want_cookie = 1; | ||
1271 | else | ||
1272 | #endif | ||
1249 | goto drop; | 1273 | goto drop; |
1250 | } | 1274 | } |
1251 | 1275 | ||
@@ -1266,39 +1290,50 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1266 | 1290 | ||
1267 | tcp_parse_options(skb, &tmp_opt, 0); | 1291 | tcp_parse_options(skb, &tmp_opt, 0); |
1268 | 1292 | ||
1293 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
1294 | tcp_clear_options(&tmp_opt); | ||
1295 | |||
1269 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | 1296 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; |
1270 | tcp_openreq_init(req, &tmp_opt, skb); | 1297 | tcp_openreq_init(req, &tmp_opt, skb); |
1271 | 1298 | ||
1272 | treq = inet6_rsk(req); | 1299 | treq = inet6_rsk(req); |
1273 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); | 1300 | ipv6_addr_copy(&treq->rmt_addr, &ipv6_hdr(skb)->saddr); |
1274 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); | 1301 | ipv6_addr_copy(&treq->loc_addr, &ipv6_hdr(skb)->daddr); |
1275 | TCP_ECN_create_request(req, tcp_hdr(skb)); | ||
1276 | treq->pktopts = NULL; | 1302 | treq->pktopts = NULL; |
1277 | if (ipv6_opt_accepted(sk, skb) || | 1303 | if (!want_cookie) |
1278 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | 1304 | TCP_ECN_create_request(req, tcp_hdr(skb)); |
1279 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | 1305 | |
1280 | atomic_inc(&skb->users); | 1306 | if (want_cookie) { |
1281 | treq->pktopts = skb; | 1307 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); |
1282 | } | 1308 | req->cookie_ts = tmp_opt.tstamp_ok; |
1283 | treq->iif = sk->sk_bound_dev_if; | 1309 | } else if (!isn) { |
1310 | if (ipv6_opt_accepted(sk, skb) || | ||
1311 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
1312 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { | ||
1313 | atomic_inc(&skb->users); | ||
1314 | treq->pktopts = skb; | ||
1315 | } | ||
1316 | treq->iif = sk->sk_bound_dev_if; | ||
1284 | 1317 | ||
1285 | /* So that link locals have meaning */ | 1318 | /* So that link locals have meaning */ |
1286 | if (!sk->sk_bound_dev_if && | 1319 | if (!sk->sk_bound_dev_if && |
1287 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) | 1320 | ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) |
1288 | treq->iif = inet6_iif(skb); | 1321 | treq->iif = inet6_iif(skb); |
1289 | 1322 | ||
1290 | if (isn == 0) | ||
1291 | isn = tcp_v6_init_sequence(skb); | 1323 | isn = tcp_v6_init_sequence(skb); |
1324 | } | ||
1292 | 1325 | ||
1293 | tcp_rsk(req)->snt_isn = isn; | 1326 | tcp_rsk(req)->snt_isn = isn; |
1294 | 1327 | ||
1295 | security_inet_conn_request(sk, skb, req); | 1328 | security_inet_conn_request(sk, skb, req); |
1296 | 1329 | ||
1297 | if (tcp_v6_send_synack(sk, req, NULL)) | 1330 | if (tcp_v6_send_synack(sk, req)) |
1298 | goto drop; | 1331 | goto drop; |
1299 | 1332 | ||
1300 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1333 | if (!want_cookie) { |
1301 | return 0; | 1334 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1335 | return 0; | ||
1336 | } | ||
1302 | 1337 | ||
1303 | drop: | 1338 | drop: |
1304 | if (req) | 1339 | if (req) |
@@ -1499,7 +1534,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1499 | #endif | 1534 | #endif |
1500 | 1535 | ||
1501 | __inet6_hash(newsk); | 1536 | __inet6_hash(newsk); |
1502 | inet_inherit_port(sk, newsk); | 1537 | __inet_inherit_port(sk, newsk); |
1503 | 1538 | ||
1504 | return newsk; | 1539 | return newsk; |
1505 | 1540 | ||
@@ -1704,7 +1739,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1704 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1739 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1705 | TCP_SKB_CB(skb)->sacked = 0; | 1740 | TCP_SKB_CB(skb)->sacked = 0; |
1706 | 1741 | ||
1707 | sk = __inet6_lookup(skb->dev->nd_net, &tcp_hashinfo, | 1742 | sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, |
1708 | &ipv6_hdr(skb)->saddr, th->source, | 1743 | &ipv6_hdr(skb)->saddr, th->source, |
1709 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), | 1744 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), |
1710 | inet6_iif(skb)); | 1745 | inet6_iif(skb)); |
@@ -1787,7 +1822,7 @@ do_time_wait: | |||
1787 | { | 1822 | { |
1788 | struct sock *sk2; | 1823 | struct sock *sk2; |
1789 | 1824 | ||
1790 | sk2 = inet6_lookup_listener(skb->dev->nd_net, &tcp_hashinfo, | 1825 | sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, |
1791 | &ipv6_hdr(skb)->daddr, | 1826 | &ipv6_hdr(skb)->daddr, |
1792 | ntohs(th->dest), inet6_iif(skb)); | 1827 | ntohs(th->dest), inet6_iif(skb)); |
1793 | if (sk2 != NULL) { | 1828 | if (sk2 != NULL) { |
@@ -2085,28 +2120,28 @@ out: | |||
2085 | return 0; | 2120 | return 0; |
2086 | } | 2121 | } |
2087 | 2122 | ||
2088 | static struct file_operations tcp6_seq_fops; | ||
2089 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { | 2123 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { |
2090 | .owner = THIS_MODULE, | ||
2091 | .name = "tcp6", | 2124 | .name = "tcp6", |
2092 | .family = AF_INET6, | 2125 | .family = AF_INET6, |
2093 | .seq_show = tcp6_seq_show, | 2126 | .seq_fops = { |
2094 | .seq_fops = &tcp6_seq_fops, | 2127 | .owner = THIS_MODULE, |
2128 | }, | ||
2129 | .seq_ops = { | ||
2130 | .show = tcp6_seq_show, | ||
2131 | }, | ||
2095 | }; | 2132 | }; |
2096 | 2133 | ||
2097 | int __init tcp6_proc_init(void) | 2134 | int tcp6_proc_init(struct net *net) |
2098 | { | 2135 | { |
2099 | return tcp_proc_register(&tcp6_seq_afinfo); | 2136 | return tcp_proc_register(net, &tcp6_seq_afinfo); |
2100 | } | 2137 | } |
2101 | 2138 | ||
2102 | void tcp6_proc_exit(void) | 2139 | void tcp6_proc_exit(struct net *net) |
2103 | { | 2140 | { |
2104 | tcp_proc_unregister(&tcp6_seq_afinfo); | 2141 | tcp_proc_unregister(net, &tcp6_seq_afinfo); |
2105 | } | 2142 | } |
2106 | #endif | 2143 | #endif |
2107 | 2144 | ||
2108 | DEFINE_PROTO_INUSE(tcpv6) | ||
2109 | |||
2110 | struct proto tcpv6_prot = { | 2145 | struct proto tcpv6_prot = { |
2111 | .name = "TCPv6", | 2146 | .name = "TCPv6", |
2112 | .owner = THIS_MODULE, | 2147 | .owner = THIS_MODULE, |
@@ -2137,12 +2172,11 @@ struct proto tcpv6_prot = { | |||
2137 | .obj_size = sizeof(struct tcp6_sock), | 2172 | .obj_size = sizeof(struct tcp6_sock), |
2138 | .twsk_prot = &tcp6_timewait_sock_ops, | 2173 | .twsk_prot = &tcp6_timewait_sock_ops, |
2139 | .rsk_prot = &tcp6_request_sock_ops, | 2174 | .rsk_prot = &tcp6_request_sock_ops, |
2140 | .hashinfo = &tcp_hashinfo, | 2175 | .h.hashinfo = &tcp_hashinfo, |
2141 | #ifdef CONFIG_COMPAT | 2176 | #ifdef CONFIG_COMPAT |
2142 | .compat_setsockopt = compat_tcp_setsockopt, | 2177 | .compat_setsockopt = compat_tcp_setsockopt, |
2143 | .compat_getsockopt = compat_tcp_getsockopt, | 2178 | .compat_getsockopt = compat_tcp_getsockopt, |
2144 | #endif | 2179 | #endif |
2145 | REF_PROTO_INUSE(tcpv6) | ||
2146 | }; | 2180 | }; |
2147 | 2181 | ||
2148 | static struct inet6_protocol tcpv6_protocol = { | 2182 | static struct inet6_protocol tcpv6_protocol = { |
@@ -2164,6 +2198,22 @@ static struct inet_protosw tcpv6_protosw = { | |||
2164 | INET_PROTOSW_ICSK, | 2198 | INET_PROTOSW_ICSK, |
2165 | }; | 2199 | }; |
2166 | 2200 | ||
2201 | static int tcpv6_net_init(struct net *net) | ||
2202 | { | ||
2203 | return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6, | ||
2204 | SOCK_RAW, IPPROTO_TCP, net); | ||
2205 | } | ||
2206 | |||
2207 | static void tcpv6_net_exit(struct net *net) | ||
2208 | { | ||
2209 | inet_ctl_sock_destroy(net->ipv6.tcp_sk); | ||
2210 | } | ||
2211 | |||
2212 | static struct pernet_operations tcpv6_net_ops = { | ||
2213 | .init = tcpv6_net_init, | ||
2214 | .exit = tcpv6_net_exit, | ||
2215 | }; | ||
2216 | |||
2167 | int __init tcpv6_init(void) | 2217 | int __init tcpv6_init(void) |
2168 | { | 2218 | { |
2169 | int ret; | 2219 | int ret; |
@@ -2177,8 +2227,7 @@ int __init tcpv6_init(void) | |||
2177 | if (ret) | 2227 | if (ret) |
2178 | goto out_tcpv6_protocol; | 2228 | goto out_tcpv6_protocol; |
2179 | 2229 | ||
2180 | ret = inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, | 2230 | ret = register_pernet_subsys(&tcpv6_net_ops); |
2181 | SOCK_RAW, IPPROTO_TCP); | ||
2182 | if (ret) | 2231 | if (ret) |
2183 | goto out_tcpv6_protosw; | 2232 | goto out_tcpv6_protosw; |
2184 | out: | 2233 | out: |
@@ -2193,7 +2242,7 @@ out_tcpv6_protosw: | |||
2193 | 2242 | ||
2194 | void tcpv6_exit(void) | 2243 | void tcpv6_exit(void) |
2195 | { | 2244 | { |
2196 | sock_release(tcp6_socket); | 2245 | unregister_pernet_subsys(&tcpv6_net_ops); |
2197 | inet6_unregister_protosw(&tcpv6_protosw); | 2246 | inet6_unregister_protosw(&tcpv6_protosw); |
2198 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); | 2247 | inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP); |
2199 | } | 2248 | } |