aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c151
1 files changed, 114 insertions, 37 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 7e41e2cbb85e..20aa95e37359 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -130,6 +130,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
130 struct ipv6_pinfo *np = inet6_sk(sk); 130 struct ipv6_pinfo *np = inet6_sk(sk);
131 struct tcp_sock *tp = tcp_sk(sk); 131 struct tcp_sock *tp = tcp_sk(sk);
132 struct in6_addr *saddr = NULL, *final_p, final; 132 struct in6_addr *saddr = NULL, *final_p, final;
133 struct rt6_info *rt;
133 struct flowi fl; 134 struct flowi fl;
134 struct dst_entry *dst; 135 struct dst_entry *dst;
135 int addr_type; 136 int addr_type;
@@ -280,6 +281,26 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
280 sk->sk_gso_type = SKB_GSO_TCPV6; 281 sk->sk_gso_type = SKB_GSO_TCPV6;
281 __ip6_dst_store(sk, dst, NULL, NULL); 282 __ip6_dst_store(sk, dst, NULL, NULL);
282 283
284 rt = (struct rt6_info *) dst;
285 if (tcp_death_row.sysctl_tw_recycle &&
286 !tp->rx_opt.ts_recent_stamp &&
287 ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) {
288 struct inet_peer *peer = rt6_get_peer(rt);
289 /*
290 * VJ's idea. We save last timestamp seen from
291 * the destination in peer table, when entering state
292 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
293 * when trying new connection.
294 */
295 if (peer) {
296 inet_peer_refcheck(peer);
297 if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) {
298 tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
299 tp->rx_opt.ts_recent = peer->tcp_ts;
300 }
301 }
302 }
303
283 icsk->icsk_ext_hdr_len = 0; 304 icsk->icsk_ext_hdr_len = 0;
284 if (np->opt) 305 if (np->opt)
285 icsk->icsk_ext_hdr_len = (np->opt->opt_flen + 306 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
@@ -906,12 +927,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
906}; 927};
907#endif 928#endif
908 929
909static struct timewait_sock_ops tcp6_timewait_sock_ops = {
910 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
911 .twsk_unique = tcp_twsk_unique,
912 .twsk_destructor= tcp_twsk_destructor,
913};
914
915static void __tcp_v6_send_check(struct sk_buff *skb, 930static void __tcp_v6_send_check(struct sk_buff *skb,
916 struct in6_addr *saddr, struct in6_addr *daddr) 931 struct in6_addr *saddr, struct in6_addr *daddr)
917{ 932{
@@ -1176,6 +1191,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1176 struct ipv6_pinfo *np = inet6_sk(sk); 1191 struct ipv6_pinfo *np = inet6_sk(sk);
1177 struct tcp_sock *tp = tcp_sk(sk); 1192 struct tcp_sock *tp = tcp_sk(sk);
1178 __u32 isn = TCP_SKB_CB(skb)->when; 1193 __u32 isn = TCP_SKB_CB(skb)->when;
1194 struct dst_entry *dst = NULL;
1179#ifdef CONFIG_SYN_COOKIES 1195#ifdef CONFIG_SYN_COOKIES
1180 int want_cookie = 0; 1196 int want_cookie = 0;
1181#else 1197#else
@@ -1273,6 +1289,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1273 TCP_ECN_create_request(req, tcp_hdr(skb)); 1289 TCP_ECN_create_request(req, tcp_hdr(skb));
1274 1290
1275 if (!isn) { 1291 if (!isn) {
1292 struct inet_peer *peer = NULL;
1293
1276 if (ipv6_opt_accepted(sk, skb) || 1294 if (ipv6_opt_accepted(sk, skb) ||
1277 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || 1295 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
1278 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { 1296 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
@@ -1285,13 +1303,57 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1285 if (!sk->sk_bound_dev_if && 1303 if (!sk->sk_bound_dev_if &&
1286 ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL) 1304 ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
1287 treq->iif = inet6_iif(skb); 1305 treq->iif = inet6_iif(skb);
1288 if (!want_cookie) { 1306
1289 isn = tcp_v6_init_sequence(skb); 1307 if (want_cookie) {
1290 } else {
1291 isn = cookie_v6_init_sequence(sk, skb, &req->mss); 1308 isn = cookie_v6_init_sequence(sk, skb, &req->mss);
1292 req->cookie_ts = tmp_opt.tstamp_ok; 1309 req->cookie_ts = tmp_opt.tstamp_ok;
1310 goto have_isn;
1293 } 1311 }
1312
1313 /* VJ's idea. We save last timestamp seen
1314 * from the destination in peer table, when entering
1315 * state TIME-WAIT, and check against it before
1316 * accepting new connection request.
1317 *
1318 * If "isn" is not zero, this request hit alive
1319 * timewait bucket, so that all the necessary checks
1320 * are made in the function processing timewait state.
1321 */
1322 if (tmp_opt.saw_tstamp &&
1323 tcp_death_row.sysctl_tw_recycle &&
1324 (dst = inet6_csk_route_req(sk, req)) != NULL &&
1325 (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
1326 ipv6_addr_equal((struct in6_addr *)peer->daddr.a6,
1327 &treq->rmt_addr)) {
1328 inet_peer_refcheck(peer);
1329 if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
1330 (s32)(peer->tcp_ts - req->ts_recent) >
1331 TCP_PAWS_WINDOW) {
1332 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
1333 goto drop_and_release;
1334 }
1335 }
1336 /* Kill the following clause, if you dislike this way. */
1337 else if (!sysctl_tcp_syncookies &&
1338 (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
1339 (sysctl_max_syn_backlog >> 2)) &&
1340 (!peer || !peer->tcp_ts_stamp) &&
1341 (!dst || !dst_metric(dst, RTAX_RTT))) {
1342 /* Without syncookies last quarter of
1343 * backlog is filled with destinations,
1344 * proven to be alive.
1345 * It means that we continue to communicate
1346 * to destinations, already remembered
1347 * to the moment of synflood.
1348 */
1349 LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n",
1350 &treq->rmt_addr, ntohs(tcp_hdr(skb)->source));
1351 goto drop_and_release;
1352 }
1353
1354 isn = tcp_v6_init_sequence(skb);
1294 } 1355 }
1356have_isn:
1295 tcp_rsk(req)->snt_isn = isn; 1357 tcp_rsk(req)->snt_isn = isn;
1296 1358
1297 security_inet_conn_request(sk, skb, req); 1359 security_inet_conn_request(sk, skb, req);
@@ -1304,6 +1366,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1304 inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); 1366 inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
1305 return 0; 1367 return 0;
1306 1368
1369drop_and_release:
1370 dst_release(dst);
1307drop_and_free: 1371drop_and_free:
1308 reqsk_free(req); 1372 reqsk_free(req);
1309drop: 1373drop:
@@ -1382,28 +1446,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1382 if (sk_acceptq_is_full(sk)) 1446 if (sk_acceptq_is_full(sk))
1383 goto out_overflow; 1447 goto out_overflow;
1384 1448
1385 if (dst == NULL) { 1449 if (!dst) {
1386 struct in6_addr *final_p, final; 1450 dst = inet6_csk_route_req(sk, req);
1387 struct flowi fl; 1451 if (!dst)
1388
1389 memset(&fl, 0, sizeof(fl));
1390 fl.proto = IPPROTO_TCP;
1391 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
1392 final_p = fl6_update_dst(&fl, opt, &final);
1393 ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
1394 fl.oif = sk->sk_bound_dev_if;
1395 fl.mark = sk->sk_mark;
1396 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
1397 fl.fl_ip_sport = inet_rsk(req)->loc_port;
1398 security_req_classify_flow(req, &fl);
1399
1400 if (ip6_dst_lookup(sk, &dst, &fl))
1401 goto out;
1402
1403 if (final_p)
1404 ipv6_addr_copy(&fl.fl6_dst, final_p);
1405
1406 if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
1407 goto out; 1452 goto out;
1408 } 1453 }
1409 1454
@@ -1476,7 +1521,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1476 1521
1477 tcp_mtup_init(newsk); 1522 tcp_mtup_init(newsk);
1478 tcp_sync_mss(newsk, dst_mtu(dst)); 1523 tcp_sync_mss(newsk, dst_mtu(dst));
1479 newtp->advmss = dst_metric(dst, RTAX_ADVMSS); 1524 newtp->advmss = dst_metric_advmss(dst);
1480 tcp_initialize_rcv_mss(newsk); 1525 tcp_initialize_rcv_mss(newsk);
1481 1526
1482 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6; 1527 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
@@ -1818,19 +1863,51 @@ do_time_wait:
1818 goto discard_it; 1863 goto discard_it;
1819} 1864}
1820 1865
1821static int tcp_v6_remember_stamp(struct sock *sk) 1866static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
1822{ 1867{
1823 /* Alas, not yet... */ 1868 struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk);
1824 return 0; 1869 struct ipv6_pinfo *np = inet6_sk(sk);
1870 struct inet_peer *peer;
1871
1872 if (!rt ||
1873 !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr)) {
1874 peer = inet_getpeer_v6(&np->daddr, 1);
1875 *release_it = true;
1876 } else {
1877 if (!rt->rt6i_peer)
1878 rt6_bind_peer(rt, 1);
1879 peer = rt->rt6i_peer;
1880 *release_it = false;
1881 }
1882
1883 return peer;
1825} 1884}
1826 1885
1886static void *tcp_v6_tw_get_peer(struct sock *sk)
1887{
1888 struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
1889 struct inet_timewait_sock *tw = inet_twsk(sk);
1890
1891 if (tw->tw_family == AF_INET)
1892 return tcp_v4_tw_get_peer(sk);
1893
1894 return inet_getpeer_v6(&tw6->tw_v6_daddr, 1);
1895}
1896
1897static struct timewait_sock_ops tcp6_timewait_sock_ops = {
1898 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
1899 .twsk_unique = tcp_twsk_unique,
1900 .twsk_destructor= tcp_twsk_destructor,
1901 .twsk_getpeer = tcp_v6_tw_get_peer,
1902};
1903
1827static const struct inet_connection_sock_af_ops ipv6_specific = { 1904static const struct inet_connection_sock_af_ops ipv6_specific = {
1828 .queue_xmit = inet6_csk_xmit, 1905 .queue_xmit = inet6_csk_xmit,
1829 .send_check = tcp_v6_send_check, 1906 .send_check = tcp_v6_send_check,
1830 .rebuild_header = inet6_sk_rebuild_header, 1907 .rebuild_header = inet6_sk_rebuild_header,
1831 .conn_request = tcp_v6_conn_request, 1908 .conn_request = tcp_v6_conn_request,
1832 .syn_recv_sock = tcp_v6_syn_recv_sock, 1909 .syn_recv_sock = tcp_v6_syn_recv_sock,
1833 .remember_stamp = tcp_v6_remember_stamp, 1910 .get_peer = tcp_v6_get_peer,
1834 .net_header_len = sizeof(struct ipv6hdr), 1911 .net_header_len = sizeof(struct ipv6hdr),
1835 .setsockopt = ipv6_setsockopt, 1912 .setsockopt = ipv6_setsockopt,
1836 .getsockopt = ipv6_getsockopt, 1913 .getsockopt = ipv6_getsockopt,
@@ -1862,7 +1939,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = {
1862 .rebuild_header = inet_sk_rebuild_header, 1939 .rebuild_header = inet_sk_rebuild_header,
1863 .conn_request = tcp_v6_conn_request, 1940 .conn_request = tcp_v6_conn_request,
1864 .syn_recv_sock = tcp_v6_syn_recv_sock, 1941 .syn_recv_sock = tcp_v6_syn_recv_sock,
1865 .remember_stamp = tcp_v4_remember_stamp, 1942 .get_peer = tcp_v4_get_peer,
1866 .net_header_len = sizeof(struct iphdr), 1943 .net_header_len = sizeof(struct iphdr),
1867 .setsockopt = ipv6_setsockopt, 1944 .setsockopt = ipv6_setsockopt,
1868 .getsockopt = ipv6_getsockopt, 1945 .getsockopt = ipv6_getsockopt,