diff options
author | Octavian Purdila <octavian.purdila@intel.com> | 2014-06-25 10:10:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-06-27 18:53:37 -0400 |
commit | 1fb6f159fd21c640a28eb65fbd62ce8c9f6a777e (patch) | |
tree | b7ba1708058d6c13ee686da1fce92a7d71b84c0f /net/ipv6/tcp_ipv6.c | |
parent | 695da14eb0af21129187ed3810e329b21262e45f (diff) |
tcp: add tcp_conn_request
Create tcp_conn_request and remove most of the code from
tcp_v4_conn_request and tcp_v6_conn_request.
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 120 |
1 files changed, 2 insertions, 118 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 8232bc7423c6..bc24ee21339a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1008,133 +1008,17 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1008 | return sk; | 1008 | return sk; |
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | /* FIXME: this is substantially similar to the ipv4 code. | ||
1012 | * Can some kind of merge be done? -- erics | ||
1013 | */ | ||
1014 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1011 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
1015 | { | 1012 | { |
1016 | struct tcp_options_received tmp_opt; | ||
1017 | struct request_sock *req; | ||
1018 | struct inet_request_sock *ireq; | ||
1019 | struct tcp_sock *tp = tcp_sk(sk); | ||
1020 | __u32 isn = TCP_SKB_CB(skb)->when; | ||
1021 | struct dst_entry *dst = NULL; | ||
1022 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
1023 | bool want_cookie = false, fastopen; | ||
1024 | struct flowi6 fl6; | ||
1025 | const struct tcp_request_sock_ops *af_ops; | ||
1026 | int err; | ||
1027 | |||
1028 | if (skb->protocol == htons(ETH_P_IP)) | 1013 | if (skb->protocol == htons(ETH_P_IP)) |
1029 | return tcp_v4_conn_request(sk, skb); | 1014 | return tcp_v4_conn_request(sk, skb); |
1030 | 1015 | ||
1031 | if (!ipv6_unicast_destination(skb)) | 1016 | if (!ipv6_unicast_destination(skb)) |
1032 | goto drop; | 1017 | goto drop; |
1033 | 1018 | ||
1034 | if ((sysctl_tcp_syncookies == 2 || | 1019 | return tcp_conn_request(&tcp6_request_sock_ops, |
1035 | inet_csk_reqsk_queue_is_full(sk)) && !isn) { | 1020 | &tcp_request_sock_ipv6_ops, sk, skb); |
1036 | want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6"); | ||
1037 | if (!want_cookie) | ||
1038 | goto drop; | ||
1039 | } | ||
1040 | 1021 | ||
1041 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { | ||
1042 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
1043 | goto drop; | ||
1044 | } | ||
1045 | |||
1046 | req = inet_reqsk_alloc(&tcp6_request_sock_ops); | ||
1047 | if (req == NULL) | ||
1048 | goto drop; | ||
1049 | |||
1050 | af_ops = tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; | ||
1051 | |||
1052 | tcp_clear_options(&tmp_opt); | ||
1053 | tmp_opt.mss_clamp = af_ops->mss_clamp; | ||
1054 | tmp_opt.user_mss = tp->rx_opt.user_mss; | ||
1055 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); | ||
1056 | |||
1057 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
1058 | tcp_clear_options(&tmp_opt); | ||
1059 | |||
1060 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | ||
1061 | tcp_openreq_init(req, &tmp_opt, skb, sk); | ||
1062 | |||
1063 | ireq = inet_rsk(req); | ||
1064 | af_ops->init_req(req, sk, skb); | ||
1065 | |||
1066 | if (security_inet_conn_request(sk, skb, req)) | ||
1067 | goto drop_and_release; | ||
1068 | |||
1069 | if (!want_cookie || tmp_opt.tstamp_ok) | ||
1070 | TCP_ECN_create_request(req, skb, sock_net(sk)); | ||
1071 | |||
1072 | if (want_cookie) { | ||
1073 | isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); | ||
1074 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1075 | } else if (!isn) { | ||
1076 | /* VJ's idea. We save last timestamp seen | ||
1077 | * from the destination in peer table, when entering | ||
1078 | * state TIME-WAIT, and check against it before | ||
1079 | * accepting new connection request. | ||
1080 | * | ||
1081 | * If "isn" is not zero, this request hit alive | ||
1082 | * timewait bucket, so that all the necessary checks | ||
1083 | * are made in the function processing timewait state. | ||
1084 | */ | ||
1085 | if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle) { | ||
1086 | dst = af_ops->route_req(sk, (struct flowi *)&fl6, req, | ||
1087 | NULL); | ||
1088 | if (dst && !tcp_peer_is_proven(req, dst, true)) { | ||
1089 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
1090 | goto drop_and_release; | ||
1091 | } | ||
1092 | } | ||
1093 | /* Kill the following clause, if you dislike this way. */ | ||
1094 | else if (!sysctl_tcp_syncookies && | ||
1095 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
1096 | (sysctl_max_syn_backlog >> 2)) && | ||
1097 | !tcp_peer_is_proven(req, dst, false)) { | ||
1098 | /* Without syncookies last quarter of | ||
1099 | * backlog is filled with destinations, | ||
1100 | * proven to be alive. | ||
1101 | * It means that we continue to communicate | ||
1102 | * to destinations, already remembered | ||
1103 | * to the moment of synflood. | ||
1104 | */ | ||
1105 | LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n", | ||
1106 | &ireq->ir_v6_rmt_addr, ntohs(tcp_hdr(skb)->source)); | ||
1107 | goto drop_and_release; | ||
1108 | } | ||
1109 | |||
1110 | isn = af_ops->init_seq(skb); | ||
1111 | } | ||
1112 | |||
1113 | if (!dst) { | ||
1114 | dst = af_ops->route_req(sk, (struct flowi *)&fl6, req, NULL); | ||
1115 | if (!dst) | ||
1116 | goto drop_and_free; | ||
1117 | } | ||
1118 | |||
1119 | tcp_rsk(req)->snt_isn = isn; | ||
1120 | tcp_openreq_init_rwin(req, sk, dst); | ||
1121 | fastopen = !want_cookie && | ||
1122 | tcp_try_fastopen(sk, skb, req, &foc, dst); | ||
1123 | err = af_ops->send_synack(sk, dst, (struct flowi *)&fl6, req, | ||
1124 | skb_get_queue_mapping(skb), &foc); | ||
1125 | if (!fastopen) { | ||
1126 | if (err || want_cookie) | ||
1127 | goto drop_and_free; | ||
1128 | |||
1129 | tcp_rsk(req)->listener = NULL; | ||
1130 | af_ops->queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
1131 | } | ||
1132 | return 0; | ||
1133 | |||
1134 | drop_and_release: | ||
1135 | dst_release(dst); | ||
1136 | drop_and_free: | ||
1137 | reqsk_free(req); | ||
1138 | drop: | 1022 | drop: |
1139 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1023 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
1140 | return 0; /* don't send reset */ | 1024 | return 0; /* don't send reset */ |