4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * This file contains functions related to TCP time wait processing. Also
28 * refer to the time wait handling comments in tcp_impl.h.
29 */
30
31 #include <sys/types.h>
32 #include <sys/strsun.h>
33 #include <sys/squeue_impl.h>
34 #include <sys/squeue.h>
35 #include <sys/callo.h>
36
37 #include <inet/common.h>
38 #include <inet/ip.h>
39 #include <inet/tcp.h>
40 #include <inet/tcp_impl.h>
41 #include <inet/tcp_cluster.h>
42
43 static void tcp_timewait_close(void *, mblk_t *, void *, ip_recv_attr_t *);
493 ASSERT(tcp != NULL);
494 TCP_TIMER_RESTART(tcp,
495 tcps->tcps_time_wait_interval);
496 }
497 tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
498 tcp->tcp_rnxt, TH_ACK);
499 goto done;
500 }
501 flags |= TH_ACK_NEEDED;
502 seg_len = 0;
503 goto process_ack;
504 }
505
506 /* Fix seg_seq, and chew the gap off the front. */
507 seg_seq = tcp->tcp_rnxt;
508 }
509
510 if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
511 /*
512 * Make sure that when we accept the connection, pick
513 * an ISS greater than (tcp_snxt + ISS_INCR/2) for the
514 * old connection.
515 *
516 * The next ISS generated is equal to tcp_iss_incr_extra
517 * + ISS_INCR/2 + other components depending on the
518 * value of tcp_strong_iss. We pre-calculate the new
519 * ISS here and compare with tcp_snxt to determine if
520 * we need to make adjustment to tcp_iss_incr_extra.
521 *
522 * The above calculation is ugly and is a
523 * waste of CPU cycles...
524 */
525 uint32_t new_iss = tcps->tcps_iss_incr_extra;
526 int32_t adj;
527 ip_stack_t *ipst = tcps->tcps_netstack->netstack_ip;
528
529 switch (tcps->tcps_strong_iss) {
530 case 2: {
531 /* Add time and MD5 components. */
532 uint32_t answer[4];
533 struct {
534 uint32_t ports;
535 in6_addr_t src;
536 in6_addr_t dst;
537 } arg;
540 mutex_enter(&tcps->tcps_iss_key_lock);
541 context = tcps->tcps_iss_key;
542 mutex_exit(&tcps->tcps_iss_key_lock);
543 arg.ports = connp->conn_ports;
544 /* We use MAPPED addresses in tcp_iss_init */
545 arg.src = connp->conn_laddr_v6;
546 arg.dst = connp->conn_faddr_v6;
547 MD5Update(&context, (uchar_t *)&arg,
548 sizeof (arg));
549 MD5Final((uchar_t *)answer, &context);
550 answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
551 new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
552 break;
553 }
554 case 1:
555 /* Add time component and min random (i.e. 1). */
556 new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
557 break;
558 default:
559 /* Add only time component. */
560 new_iss += (uint32_t)gethrestime_sec() * ISS_INCR;
561 break;
562 }
563 if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
564 /*
565 * New ISS not guaranteed to be ISS_INCR/2
566 * ahead of the current tcp_snxt, so add the
567 * difference to tcp_iss_incr_extra.
568 */
569 tcps->tcps_iss_incr_extra += adj;
570 }
571 /*
572 * If tcp_clean_death() can not perform the task now,
573 * drop the SYN packet and let the other side re-xmit.
574 * Otherwise pass the SYN packet back in, since the
575 * old tcp state has been cleaned up or freed.
576 */
577 if (tcp_clean_death(tcp, 0) == -1)
578 goto done;
579 nconnp = ipcl_classify(mp, ira, ipst);
580 if (nconnp != NULL) {
581 TCP_STAT(tcps, tcp_time_wait_syn_success);
582 /* Drops ref on nconnp */
583 tcp_reinput(nconnp, mp, ira, ipst);
584 return;
585 }
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2011, Joyent Inc. All rights reserved.
25 */
26
27 /*
28 * This file contains functions related to TCP time wait processing. Also
29 * refer to the time wait handling comments in tcp_impl.h.
30 */
31
32 #include <sys/types.h>
33 #include <sys/strsun.h>
34 #include <sys/squeue_impl.h>
35 #include <sys/squeue.h>
36 #include <sys/callo.h>
37
38 #include <inet/common.h>
39 #include <inet/ip.h>
40 #include <inet/tcp.h>
41 #include <inet/tcp_impl.h>
42 #include <inet/tcp_cluster.h>
43
44 static void tcp_timewait_close(void *, mblk_t *, void *, ip_recv_attr_t *);
494 ASSERT(tcp != NULL);
495 TCP_TIMER_RESTART(tcp,
496 tcps->tcps_time_wait_interval);
497 }
498 tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
499 tcp->tcp_rnxt, TH_ACK);
500 goto done;
501 }
502 flags |= TH_ACK_NEEDED;
503 seg_len = 0;
504 goto process_ack;
505 }
506
507 /* Fix seg_seq, and chew the gap off the front. */
508 seg_seq = tcp->tcp_rnxt;
509 }
510
511 if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
512 /*
513 * Make sure that when we accept the connection, pick
514 * an ISS greater than (tcp_snxt + tcp_iss_incr/2) for the
515 * old connection.
516 *
517 * The next ISS generated is equal to tcp_iss_incr_extra
518 * + tcp_iss_incr/2 + other components depending on the
519 * value of tcp_strong_iss. We pre-calculate the new
520 * ISS here and compare with tcp_snxt to determine if
521 * we need to make adjustment to tcp_iss_incr_extra.
522 *
523 * The above calculation is ugly and is a
524 * waste of CPU cycles...
525 */
526 uint32_t new_iss = tcps->tcps_iss_incr_extra;
527 int32_t adj;
528 ip_stack_t *ipst = tcps->tcps_netstack->netstack_ip;
529
530 switch (tcps->tcps_strong_iss) {
531 case 2: {
532 /* Add time and MD5 components. */
533 uint32_t answer[4];
534 struct {
535 uint32_t ports;
536 in6_addr_t src;
537 in6_addr_t dst;
538 } arg;
541 mutex_enter(&tcps->tcps_iss_key_lock);
542 context = tcps->tcps_iss_key;
543 mutex_exit(&tcps->tcps_iss_key_lock);
544 arg.ports = connp->conn_ports;
545 /* We use MAPPED addresses in tcp_iss_init */
546 arg.src = connp->conn_laddr_v6;
547 arg.dst = connp->conn_faddr_v6;
548 MD5Update(&context, (uchar_t *)&arg,
549 sizeof (arg));
550 MD5Final((uchar_t *)answer, &context);
551 answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
552 new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
553 break;
554 }
555 case 1:
556 /* Add time component and min random (i.e. 1). */
557 new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
558 break;
559 default:
560 /* Add only time component. */
561 new_iss += (uint32_t)gethrestime_sec() *
562 tcps->tcps_iss_incr;
563 break;
564 }
565 if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
566 /*
567 * New ISS not guaranteed to be tcp_iss_incr/2
568 * ahead of the current tcp_snxt, so add the
569 * difference to tcp_iss_incr_extra.
570 */
571 tcps->tcps_iss_incr_extra += adj;
572 }
573 /*
574 * If tcp_clean_death() can not perform the task now,
575 * drop the SYN packet and let the other side re-xmit.
576 * Otherwise pass the SYN packet back in, since the
577 * old tcp state has been cleaned up or freed.
578 */
579 if (tcp_clean_death(tcp, 0) == -1)
580 goto done;
581 nconnp = ipcl_classify(mp, ira, ipst);
582 if (nconnp != NULL) {
583 TCP_STAT(tcps, tcp_time_wait_syn_success);
584 /* Drops ref on nconnp */
585 tcp_reinput(nconnp, mp, ira, ipst);
586 return;
587 }
|