usr/src/uts/common/inet/tcp/tcp.c
author masputra
Sat, 22 Oct 2005 22:50:14 -0700
changeset 741 40027a3621ac
parent 740 70e4862c9a1a
child 766 c521de78a32f
permissions -rw-r--r--
PSARC 2005/082 Yosemite: UDP Performance Enhancement 4796051 Solaris needs a more complete HW checksumming support 4905227 duplicate macros in ipclassifier.h and ip.h 4915681 need hardware checksum offload for the case of IP/UDP reassembly 6201076 outbound flow-control dysfunctional, ip to ce using mdt 6223331 ipv6 flow control may corrupt UDP packets 6223809 16-bit aligned IP header should be allowed for all x86 platforms 6275398 Galaxy hangs when running lmbench 6281836 Yosemite project integration into Solaris 6281885 xge needs to support IPv6 checksum offload 6282776 IPv6 NCE fast path is not created for incoming solicitation 6304890 IP transmit-side checksum logic needs to be tightened 6304902 IP6_IN_NOCKSUM is obsolete and should be torched 6304904 UDP should reject TI_GETPEERNAME for non-connected endpoint 6306768 IP and UDP device and module definitions need to be centralized
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
/* Copyright (c) 1990 Mentat Inc. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
const char tcp_version[] = "%Z%%M%	%I%	%E% SMI";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/stream.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/strsubr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/stropts.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/strlog.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/strsun.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#define	_SUN_TPI_VERSION 2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/tihdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/timod.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/ddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/sunddi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/suntpi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/xti_inet.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/ethernet.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/cpuvar.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/dlpi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/multidata.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/multidata_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/pattr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <sys/zone.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <sys/signal.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <sys/socket.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <sys/sockio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <sys/isa_defs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <sys/md5.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <sys/random.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <netinet/in.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <netinet/tcp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <netinet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
#include <netinet/icmp6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <net/if.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#include <net/route.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <inet/ipsec_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include <inet/common.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <inet/ip.h>
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
    76
#include <inet/ip_impl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#include <inet/ip6.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#include <inet/ip_ndp.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
#include <inet/mi.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#include <inet/mib2.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
#include <inet/nd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
#include <inet/optcom.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
#include <inet/snmpcom.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
#include <inet/kstatcom.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
#include <inet/tcp.h>
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
    86
#include <inet/tcp_impl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
#include <net/pfkeyv2.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
#include <inet/ipsec_info.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
#include <inet/ipdrop.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
#include <inet/tcp_trace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
#include <inet/ipclassifier.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
#include <inet/ip_ire.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
#include <inet/ip_if.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
#include <inet/ipp_common.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
#include <sys/squeue.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
 * TCP Notes: aka FireEngine Phase I (PSARC 2002/433)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 * (Read the detailed design doc in PSARC case directory)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 * The entire tcp state is contained in tcp_t and conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
 * which are allocated in tandem using ipcl_conn_create() and passing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
 * IPCL_CONNTCP as a flag. We use 'conn_ref' and 'conn_lock' to protect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
 * the references on the tcp_t. The tcp_t structure is never compressed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
 * and packets always land on the correct TCP perimeter from the time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
 * eager is created till the time tcp_t dies (as such the old mentat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
 * TCP global queue is not used for detached state and no IPSEC checking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 * is required). The global queue is still allocated to send out resets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 * for connection which have no listeners and IP directly calls
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
 * tcp_xmit_listeners_reset() which does any policy check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
 * Protection and Synchronisation mechanism:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
 * The tcp data structure does not use any kind of lock for protecting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
 * its state but instead uses 'squeues' for mutual exclusion from various
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
 * read and write side threads. To access a tcp member, the thread should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
 * always be behind squeue (via squeue_enter, squeue_enter_nodrain, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
 * squeue_fill). Since the squeues allow a direct function call, caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
 * can pass any tcp function having prototype of edesc_t as argument
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
 * (different from traditional STREAMs model where packets come in only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
 * designated entry points). The list of functions that can be directly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
 * called via squeue are listed before the usual function prototype.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
 * Referencing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
 * TCP is MT-Hot and we use a reference based scheme to make sure that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 * tcp structure doesn't disappear when its needed. When the application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 * creates an outgoing connection or accepts an incoming connection, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 * start out with 2 references on 'conn_ref'. One for TCP and one for IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 * The IP reference is just a symbolic reference since ip_tcpclose()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 * looks at tcp structure after tcp_close_output() returns which could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
 * have dropped the last TCP reference. So as long as the connection is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
 * in attached state i.e. !TCP_IS_DETACHED, we have 2 references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
 * conn_t. The classifier puts its own reference when the connection is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
 * inserted in listen or connected hash. Anytime a thread needs to enter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
 * the tcp connection perimeter, it retrieves the conn/tcp from q->ptr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
 * on write side or by doing a classify on read side and then puts a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
 * reference on the conn before doing squeue_enter/tryenter/fill. For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
 * read side, the classifier itself puts the reference under fanout lock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
 * to make sure that tcp can't disappear before it gets processed. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
 * squeue will drop this reference automatically so the called function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
 * doesn't have to do a DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
 * Opening a new connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 * The outgoing connection open is pretty simple. ip_tcpopen() does the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 * work in creating the conn/tcp structure and initializing it. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 * squeue assignment is done based on the CPU the application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
 * is running on. So for outbound connections, processing is always done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
 * on application CPU which might be different from the incoming CPU
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
 * being interrupted by the NIC. An optimal way would be to figure out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
 * the NIC <-> CPU binding at listen time, and assign the outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
 * connection to the squeue attached to the CPU that will be interrupted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
 * for incoming packets (we know the NIC based on the bind IP address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
 * This might seem like a problem if more data is going out but the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
 * fact is that in most cases the transmit is ACK driven transmit where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
 * the outgoing data normally sits on TCP's xmit queue waiting to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
 * transmitted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
 * Accepting a connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
 * This is a more interesting case because of various races involved in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
 * establishing a eager in its own perimeter. Read the meta comment on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
 * top of tcp_conn_request(). But briefly, the squeue is picked by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
 * ip_tcp_input()/ip_fanout_tcp_v6() based on the interrupted CPU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 * Closing a connection:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
 * The close is fairly straight forward. tcp_close() calls tcp_close_output()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
 * via squeue to do the close and mark the tcp as detached if the connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
 * was in state TCPS_ESTABLISHED or greater. In the later case, TCP keep its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
 * reference but tcp_close() drop IP's reference always. So if tcp was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
 * not killed, it is sitting in time_wait list with 2 reference - 1 for TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
 * and 1 because it is in classifier's connected hash. This is the condition
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
 * we use to determine that its OK to clean up the tcp outside of squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
 * when time wait expires (check the ref under fanout and conn_lock and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
 * if it is 2, remove it from fanout hash and kill it).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
 * Although close just drops the necessary references and marks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 * tcp_detached state, tcp_close needs to know the tcp_detached has been
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 * set (under squeue) before letting the STREAM go away (because a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 * inbound packet might attempt to go up the STREAM while the close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
 * has happened and tcp_detached is not set). So a special lock and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
 * flag is used along with a condition variable (tcp_closelock, tcp_closed,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
 * and tcp_closecv) to signal tcp_close that tcp_close_out() has marked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
 * tcp_detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
 * Special provisions and fast paths:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
 * We make special provision for (AF_INET, SOCK_STREAM) sockets which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
 * can't have 'ipv6_recvpktinfo' set and for these type of sockets, IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
 * will never send a M_CTL to TCP. As such, ip_tcp_input() which handles
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
 * all TCP packets from the wire makes a IPCL_IS_TCP4_CONNECTED_NO_POLICY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
 * check to send packets directly to tcp_rput_data via squeue. Everyone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
 * else comes through tcp_input() on the read side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
 * We also make special provisions for sockfs by marking tcp_issocket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
 * whenever we have only sockfs on top of TCP. This allows us to skip
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
 * putting the tcp in acceptor hash since a sockfs listener can never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
 * become acceptor and also avoid allocating a tcp_t for acceptor STREAM
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
 * since eager has already been allocated and the accept now happens
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
 * on acceptor STREAM. There is a big blob of comment on top of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
 * tcp_conn_request explaining the new accept. When socket is POP'd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
 * sockfs sends us an ioctl to mark the fact and we go back to old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
 * behaviour. Once tcp_issocket is unset, its never set for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
 * life of that connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
 * IPsec notes :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
 * Since a packet is always executed on the correct TCP perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
 * all IPsec processing is defered to IP including checking new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
 * connections and setting IPSEC policies for new connection. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
 * only exception is tcp_xmit_listeners_reset() which is called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
 * directly from IP and needs to policy check to see if TH_RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
 * can be sent out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
extern major_t TCP6_MAJ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
 * Values for squeue switch:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
 * 1: squeue_enter_nodrain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
 * 2: squeue_enter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
 * 3: squeue_fill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
int tcp_squeue_close = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
int tcp_squeue_wput = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
squeue_func_t tcp_squeue_close_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
squeue_func_t tcp_squeue_wput_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
 * This controls how tiny a write must be before we try to copy it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
 * into the the mblk on the tail of the transmit queue.  Not much
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
 * speedup is observed for values larger than sixteen.  Zero will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
 * disable the optimisation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
int tcp_tx_pull_len = 16;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
 * TCP Statistics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
 * How TCP statistics work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
 * There are two types of statistics invoked by two macros.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
 * TCP_STAT(name) does non-atomic increment of a named stat counter. It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
 * supposed to be used in non MT-hot paths of the code.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
 * TCP_DBGSTAT(name) does atomic increment of a named stat counter. It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
 * supposed to be used for DEBUG purposes and may be used on a hot path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
 * Both TCP_STAT and TCP_DBGSTAT counters are available using kstat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
 * (use "kstat tcp" to get them).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
 * There is also additional debugging facility that marks tcp_clean_death()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
 * instances and saves them in tcp_t structure. It is triggered by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
 * TCP_TAG_CLEAN_DEATH define. Also, there is a global array of counters for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
 * tcp_clean_death() calls that counts the number of times each tag was hit. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
 * is triggered by TCP_CLD_COUNTERS define.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
 * How to add new counters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
 * 1) Add a field in the tcp_stat structure describing your counter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
 * 2) Add a line in tcp_statistics with the name of the counter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
 *    IMPORTANT!! - make sure that both are in sync !!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
 * 3) Use either TCP_STAT or TCP_DBGSTAT with the name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
 * Please avoid using private counters which are not kstat-exported.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
 * TCP_TAG_CLEAN_DEATH set to 1 enables tagging of tcp_clean_death() instances
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
 * in tcp_t structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
 * TCP_MAX_CLEAN_DEATH_TAG is the maximum number of possible clean death tags.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
#ifndef TCP_DEBUG_COUNTER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
#define	TCP_DEBUG_COUNTER 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
#define	TCP_DEBUG_COUNTER 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   289
#define	TCP_CLD_COUNTERS 0
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
#define	TCP_TAG_CLEAN_DEATH 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
#define	TCP_MAX_CLEAN_DEATH_TAG 32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
#ifdef lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
static int _lint_dummy_;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
#if TCP_CLD_COUNTERS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
static uint_t tcp_clean_death_stat[TCP_MAX_CLEAN_DEATH_TAG];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
#define	TCP_CLD_STAT(x) tcp_clean_death_stat[x]++
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
#elif defined(lint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
#define	TCP_CLD_STAT(x) ASSERT(_lint_dummy_ == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
#define	TCP_CLD_STAT(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
#if TCP_DEBUG_COUNTER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
#define	TCP_DBGSTAT(x) atomic_add_64(&(tcp_statistics.x.value.ui64), 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
#elif defined(lint)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
#define	TCP_DBGSTAT(x) ASSERT(_lint_dummy_ == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
#define	TCP_DBGSTAT(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   315
tcp_stat_t tcp_statistics = {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	{ "tcp_time_wait",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
	{ "tcp_time_wait_syn",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	{ "tcp_time_wait_success",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	{ "tcp_time_wait_fail",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	{ "tcp_reinput_syn",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	{ "tcp_ip_output",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	{ "tcp_detach_non_time_wait",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	{ "tcp_detach_time_wait",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	{ "tcp_time_wait_reap",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
	{ "tcp_clean_death_nondetached",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	{ "tcp_reinit_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
	{ "tcp_eager_err1",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
	{ "tcp_eager_err2",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	{ "tcp_eager_blowoff_calls",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	{ "tcp_eager_blowoff_q",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
	{ "tcp_eager_blowoff_q0",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
	{ "tcp_not_hard_bound",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
	{ "tcp_no_listener",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
	{ "tcp_found_eager",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
	{ "tcp_wrong_queue",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	{ "tcp_found_eager_binding1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
	{ "tcp_found_eager_bound1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
	{ "tcp_eager_has_listener1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	{ "tcp_open_alloc",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
	{ "tcp_open_detached_alloc",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
	{ "tcp_rput_time_wait",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
	{ "tcp_listendrop",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
	{ "tcp_listendropq0",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	{ "tcp_wrong_rq",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
	{ "tcp_rsrv_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
	{ "tcp_eagerfree2",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
	{ "tcp_eagerfree3",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
	{ "tcp_eagerfree4",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	{ "tcp_eagerfree5",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
	{ "tcp_timewait_syn_fail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
	{ "tcp_listen_badflags",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
	{ "tcp_timeout_calls",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
	{ "tcp_timeout_cached_alloc",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
	{ "tcp_timeout_cancel_reqs",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
	{ "tcp_timeout_canceled",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
	{ "tcp_timermp_alloced",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	{ "tcp_timermp_freed",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	{ "tcp_timermp_allocfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	{ "tcp_timermp_allocdblfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	{ "tcp_push_timer_cnt",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	{ "tcp_ack_timer_cnt",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	{ "tcp_ire_null1",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
	{ "tcp_ire_null",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	{ "tcp_ip_send",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	{ "tcp_ip_ire_send",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	{ "tcp_wsrv_called",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	{ "tcp_flwctl_on",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	{ "tcp_timer_fire_early",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	{ "tcp_timer_fire_miss",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	{ "tcp_freelist_cleanup",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
	{ "tcp_rput_v6_error",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	{ "tcp_out_sw_cksum",		KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   373
	{ "tcp_out_sw_cksum_bytes",	KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
	{ "tcp_zcopy_on",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
	{ "tcp_zcopy_off",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	{ "tcp_zcopy_backoff",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	{ "tcp_zcopy_disable",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
	{ "tcp_mdt_pkt_out",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
	{ "tcp_mdt_pkt_out_v4",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
	{ "tcp_mdt_pkt_out_v6",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
	{ "tcp_mdt_discarded",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
	{ "tcp_mdt_conn_halted1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
	{ "tcp_mdt_conn_halted2",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
	{ "tcp_mdt_conn_halted3",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	{ "tcp_mdt_conn_resumed1",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
	{ "tcp_mdt_conn_resumed2",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
	{ "tcp_mdt_legacy_small",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	{ "tcp_mdt_legacy_all",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
	{ "tcp_mdt_legacy_ret",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	{ "tcp_mdt_allocfail",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	{ "tcp_mdt_addpdescfail",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
	{ "tcp_mdt_allocd",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	{ "tcp_mdt_linked",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	{ "tcp_fusion_flowctl",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	{ "tcp_fusion_backenabled",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	{ "tcp_fusion_urg",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	{ "tcp_fusion_putnext",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	{ "tcp_fusion_unfusable",	KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	{ "tcp_fusion_aborted",		KSTAT_DATA_UINT64 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	{ "tcp_fusion_unqualified",	KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   401
	{ "tcp_fusion_rrw_busy",	KSTAT_DATA_UINT64 },
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   402
	{ "tcp_fusion_rrw_msgcnt",	KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
	{ "tcp_in_ack_unsent_drop",	KSTAT_DATA_UINT64 },
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
   404
	{ "tcp_sock_fallback",		KSTAT_DATA_UINT64 },
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
static kstat_t *tcp_kstat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
 * Call either ip_output or ip_output_v6. This replaces putnext() calls on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
 * tcp write side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
#define	CALL_IP_WPUT(connp, q, mp) {					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
	ASSERT(((q)->q_flag & QREADR) == 0);				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
	TCP_DBGSTAT(tcp_ip_output);					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
	connp->conn_send(connp, (mp), (q), IP_WPUT);			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
/* Macros for timestamp comparisons */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
#define	TSTMP_GEQ(a, b)	((int32_t)((a)-(b)) >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
#define	TSTMP_LT(a, b)	((int32_t)((a)-(b)) < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
 * Parameters for TCP Initial Send Sequence number (ISS) generation.  When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
 * tcp_strong_iss is set to 1, which is the default, the ISS is calculated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
 * by adding three components: a time component which grows by 1 every 4096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
 * nanoseconds (versus every 4 microseconds suggested by RFC 793, page 27);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
 * a per-connection component which grows by 125000 for every new connection;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
 * and an "extra" component that grows by a random amount centered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
 * approximately on 64000.  This causes the the ISS generator to cycle every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
 * 4.89 hours if no TCP connections are made, and faster if connections are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
 * made.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
 * When tcp_strong_iss is set to 0, ISS is calculated by adding two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
 * components: a time component which grows by 250000 every second; and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
 * a per-connection component which grows by 125000 for every new connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
 * A third method, when tcp_strong_iss is set to 2, for generating ISS is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
 * prescribed by Steve Bellovin.  This involves adding time, the 125000 per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
 * connection, and a one-way hash (MD5) of the connection ID <sport, dport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
 * src, dst>, a "truly" random (per RFC 1750) number, and a console-entered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
 * password.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
#define	ISS_INCR	250000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
#define	ISS_NSEC_SHT	12
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
static uint32_t tcp_iss_incr_extra;	/* Incremented for each connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
static kmutex_t tcp_iss_key_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
static MD5_CTX tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
static sin_t	sin_null;	/* Zero address for quick clears */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
static sin6_t	sin6_null;	/* Zero address for quick clears */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
/* Packet dropper for TCP IPsec policy drops. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
static ipdropper_t tcp_dropper;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
 * This implementation follows the 4.3BSD interpretation of the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
 * pointer and not RFC 1122. Switching to RFC 1122 behavior would cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
 * incompatible changes in protocols like telnet and rlogin.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
#define	TCP_OLD_URP_INTERPRETATION	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
#define	TCP_IS_DETACHED_NONEAGER(tcp)	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	(TCP_IS_DETACHED(tcp) && \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	    (!(tcp)->tcp_hard_binding))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
 * TCP reassembly macros.  We hide starting and ending sequence numbers in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
 * b_next and b_prev of messages on the reassembly queue.  The messages are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
 * chained using b_cont.  These macros are used in tcp_reass() so we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
 * have to see the ugly casts and assignments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
#define	TCP_REASS_SEQ(mp)		((uint32_t)(uintptr_t)((mp)->b_next))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
#define	TCP_REASS_SET_SEQ(mp, u)	((mp)->b_next = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
					(mblk_t *)(uintptr_t)(u))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
#define	TCP_REASS_END(mp)		((uint32_t)(uintptr_t)((mp)->b_prev))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
#define	TCP_REASS_SET_END(mp, u)	((mp)->b_prev = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
					(mblk_t *)(uintptr_t)(u))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
 * Implementation of TCP Timers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
 * =============================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
 * INTERFACE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
 * There are two basic functions dealing with tcp timers:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
 *	timeout_id_t	tcp_timeout(connp, func, time)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
 * 	clock_t		tcp_timeout_cancel(connp, timeout_id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
 *	TCP_TIMER_RESTART(tcp, intvl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
 * tcp_timeout() starts a timer for the 'tcp' instance arranging to call 'func'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
 * after 'time' ticks passed. The function called by timeout() must adhere to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
 * the same restrictions as a driver soft interrupt handler - it must not sleep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
 * or call other functions that might sleep. The value returned is the opaque
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
 * non-zero timeout identifier that can be passed to tcp_timeout_cancel() to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
 * cancel the request. The call to tcp_timeout() may fail in which case it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
 * returns zero. This is different from the timeout(9F) function which never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
 * The call-back function 'func' always receives 'connp' as its single
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
 * argument. It is always executed in the squeue corresponding to the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
 * structure. The tcp structure is guaranteed to be present at the time the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
 * call-back is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
 * NOTE: The call-back function 'func' is never called if tcp is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
 * 	the TCPS_CLOSED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
 * tcp_timeout_cancel() attempts to cancel a pending tcp_timeout()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
 * request. locks acquired by the call-back routine should not be held across
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
 * the call to tcp_timeout_cancel() or a deadlock may result.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
 * tcp_timeout_cancel() returns -1 if it can not cancel the timeout request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
 * Otherwise, it returns an integer value greater than or equal to 0. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
 * particular, if the call-back function is already placed on the squeue, it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
 * not be canceled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
 * NOTE: both tcp_timeout() and tcp_timeout_cancel() should always be called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
 * 	within squeue context corresponding to the tcp instance. Since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
 *	call-back is also called via the same squeue, there are no race
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
 *	conditions described in untimeout(9F) manual page since all calls are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
 *	strictly serialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
 *      TCP_TIMER_RESTART() is a macro that attempts to cancel a pending timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
 *	stored in tcp_timer_tid and starts a new one using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
 *	MSEC_TO_TICK(intvl). It always uses tcp_timer() function as a call-back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
 *	and stores the return value of tcp_timeout() in the tcp->tcp_timer_tid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
 *	field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
 * NOTE: since the timeout cancellation is not guaranteed, the cancelled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
 *	call-back may still be called, so it is possible tcp_timer() will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
 *	called several times. This should not be a problem since tcp_timer()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
 *	should always check the tcp instance state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
 * IMPLEMENTATION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
 * TCP timers are implemented using three-stage process. The call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
 * tcp_timeout() uses timeout(9F) function to call tcp_timer_callback() function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
 * when the timer expires. The tcp_timer_callback() arranges the call of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
 * tcp_timer_handler() function via squeue corresponding to the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
 * instance. The tcp_timer_handler() calls actual requested timeout call-back
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
 * and passes tcp instance as an argument to it. Information is passed between
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
 * stages using the tcp_timer_t structure which contains the connp pointer, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
 * tcp call-back to call and the timeout id returned by the timeout(9F).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
 * The tcp_timer_t structure is not used directly, it is embedded in an mblk_t -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
 * like structure that is used to enter an squeue. The mp->b_rptr of this pseudo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
 * mblk points to the beginning of tcp_timer_t structure. The tcp_timeout()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
 * returns the pointer to this mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
 * The pseudo mblk is allocated from a special tcp_timer_cache kmem cache. It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
 * looks like a normal mblk without actual dblk attached to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
 * To optimize performance each tcp instance holds a small cache of timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
 * mblocks. In the current implementation it caches up to two timer mblocks per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
 * tcp instance. The cache is preserved over tcp frees and is only freed when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
 * the whole tcp structure is destroyed by its kmem destructor. Since all tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
 * timer processing happens on a corresponding squeue, the cache manipulation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
 * does not require any locks. Experiments show that majority of timer mblocks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
 * allocations are satisfied from the tcp cache and do not involve kmem calls.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
 * The tcp_timeout() places a refhold on the connp instance which guarantees
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
 * that it will be present at the time the call-back function fires. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
 * tcp_timer_handler() drops the reference after calling the call-back, so the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
 * call-back function does not need to manipulate the references explicitly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
typedef struct tcp_timer_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
	void 	(*tcpt_proc)(void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	timeout_id_t   tcpt_tid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
} tcp_timer_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
static kmem_cache_t *tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
kmem_cache_t	*tcp_sack_info_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
kmem_cache_t	*tcp_iphc_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
 * For scalability, we must not run a timer for every TCP connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
 * in TIME_WAIT state.  To see why, consider (for time wait interval of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
 * 4 minutes):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
 *	1000 connections/sec * 240 seconds/time wait = 240,000 active conn's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
 * This list is ordered by time, so you need only delete from the head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
 * until you get to entries which aren't old enough to delete yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
 * The list consists of only the detached TIME_WAIT connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
 * Note that the timer (tcp_time_wait_expire) is started when the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
 * becomes detached TIME_WAIT (either by changing the state and already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
 * being detached or the other way around). This means that the TIME_WAIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
 * state can be extended (up to doubled) if the connection doesn't become
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
 * detached for a long time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
 * The list manipulations (including tcp_time_wait_next/prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
 * are protected by the tcp_time_wait_lock. The content of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
 * detached TIME_WAIT connections is protected by the normal perimeters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
typedef struct tcp_squeue_priv_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	kmutex_t	tcp_time_wait_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
				/* Protects the next 3 globals */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
	timeout_id_t	tcp_time_wait_tid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
	tcp_t		*tcp_time_wait_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	tcp_t		*tcp_time_wait_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
	tcp_t		*tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
} tcp_squeue_priv_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
 * TCP_TIME_WAIT_DELAY governs how often the time_wait_collector runs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
 * Running it every 5 seconds seems to give the best results.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
#define	TCP_TIME_WAIT_DELAY drv_usectohz(5000000)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
#define	TCP_XMIT_LOWATER	4096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
#define	TCP_XMIT_HIWATER	49152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
#define	TCP_RECV_LOWATER	2048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
#define	TCP_RECV_HIWATER	49152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
 *  PAWS needs a timer for 24 days.  This is the number of ticks in 24 days
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
#define	PAWS_TIMEOUT	((clock_t)(24*24*60*60*hz))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
#define	TIDUSZ	4096	/* transport interface data unit size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
 * Bind hash list size and has function.  It has to be a power of 2 for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
 * hashing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
#define	TCP_BIND_FANOUT_SIZE	512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
#define	TCP_BIND_HASH(lport) (ntohs(lport) & (TCP_BIND_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
 * Size of listen and acceptor hash list.  It has to be a power of 2 for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
 * hashing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
#define	TCP_FANOUT_SIZE		256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
#ifdef	_ILP32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
#define	TCP_ACCEPTOR_HASH(accid)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
		(((uint_t)(accid) >> 8) & (TCP_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
#define	TCP_ACCEPTOR_HASH(accid)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
		((uint_t)(accid) & (TCP_FANOUT_SIZE - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
#endif	/* _ILP32 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
#define	IP_ADDR_CACHE_SIZE	2048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
#define	IP_ADDR_CACHE_HASH(faddr)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
	(ntohl(faddr) & (IP_ADDR_CACHE_SIZE -1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
/* Hash for HSPs uses all 32 bits, since both networks and hosts are in table */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
#define	TCP_HSP_HASH_SIZE 256
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
#define	TCP_HSP_HASH(addr)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
	(((addr>>24) ^ (addr >>16) ^			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	    (addr>>8) ^ (addr)) % TCP_HSP_HASH_SIZE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
 * TCP options struct returned from tcp_parse_options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
typedef struct tcp_opt_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
	uint32_t	tcp_opt_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	uint32_t	tcp_opt_wscale;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
	uint32_t	tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
	uint32_t	tcp_opt_ts_ecr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
} tcp_opt_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
 * RFC1323-recommended phrasing of TSTAMP option, for easier parsing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
#ifdef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
#define	TCPOPT_NOP_NOP_TSTAMP ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
	(TCPOPT_TSTAMP << 8) | 10)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
#define	TCPOPT_NOP_NOP_TSTAMP ((10 << 24) | (TCPOPT_TSTAMP << 16) | \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	(TCPOPT_NOP << 8) | TCPOPT_NOP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
 * Flags returned from tcp_parse_options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
#define	TCP_OPT_MSS_PRESENT	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
#define	TCP_OPT_WSCALE_PRESENT	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
#define	TCP_OPT_TSTAMP_PRESENT	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
#define	TCP_OPT_SACK_OK_PRESENT	8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
#define	TCP_OPT_SACK_PRESENT	16
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
/* TCP option length */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
#define	TCPOPT_NOP_LEN		1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
#define	TCPOPT_MAXSEG_LEN	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
#define	TCPOPT_WS_LEN		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
#define	TCPOPT_REAL_WS_LEN	(TCPOPT_WS_LEN+1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
#define	TCPOPT_TSTAMP_LEN	10
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
#define	TCPOPT_REAL_TS_LEN	(TCPOPT_TSTAMP_LEN+2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
#define	TCPOPT_SACK_OK_LEN	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
#define	TCPOPT_REAL_SACK_OK_LEN	(TCPOPT_SACK_OK_LEN+2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
#define	TCPOPT_REAL_SACK_LEN	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
#define	TCPOPT_MAX_SACK_LEN	36
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
#define	TCPOPT_HEADER_LEN	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
/* TCP cwnd burst factor. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
#define	TCP_CWND_INFINITE	65535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
#define	TCP_CWND_SS		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
#define	TCP_CWND_NORMAL		5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
/* Maximum TCP initial cwin (start/restart). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
#define	TCP_MAX_INIT_CWND	8
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
 * Initialize cwnd according to RFC 3390.  def_max_init_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
 * either tcp_slow_start_initial or tcp_slow_start_after idle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
 * depending on the caller.  If the upper layer has not used the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
 * TCP_INIT_CWND option to change the initial cwnd, tcp_init_cwnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
 * should be 0 and we use the formula in RFC 3390 to set tcp_cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
 * If the upper layer has changed set the tcp_init_cwnd, just use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
 * it to calculate the tcp_cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
#define	SET_TCP_INIT_CWND(tcp, mss, def_max_init_cwnd)			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
{									\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
	if ((tcp)->tcp_init_cwnd == 0) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
		(tcp)->tcp_cwnd = MIN(def_max_init_cwnd * (mss),	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
		    MIN(4 * (mss), MAX(2 * (mss), 4380 / (mss) * (mss)))); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
	} else {							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
		(tcp)->tcp_cwnd = (tcp)->tcp_init_cwnd * (mss);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
	tcp->tcp_cwnd_cnt = 0;						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
/* TCP Timer control structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
typedef struct tcpt_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
	pfv_t	tcpt_pfv;	/* The routine we are to call */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
	tcp_t	*tcpt_tcp;	/* The parameter we are to pass in */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
} tcpt_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
/* Host Specific Parameter structure */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
typedef struct tcp_hsp {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
	struct tcp_hsp	*tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	in6_addr_t	tcp_hsp_addr_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	in6_addr_t	tcp_hsp_subnet_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
	uint_t		tcp_hsp_vers;	/* IPV4_VERSION | IPV6_VERSION */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
	int32_t		tcp_hsp_sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
	int32_t		tcp_hsp_recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
	int32_t		tcp_hsp_tstamp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
} tcp_hsp_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
#define	tcp_hsp_addr	V4_PART_OF_V6(tcp_hsp_addr_v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
#define	tcp_hsp_subnet	V4_PART_OF_V6(tcp_hsp_subnet_v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
 * Functions called directly via squeue having a prototype of edesc_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
void		tcp_conn_request(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
static void	tcp_wput_nondata(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
void		tcp_accept_finish(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
static void	tcp_wput_ioctl(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
static void	tcp_wput_proto(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
void 		tcp_input(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
void		tcp_rput_data(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
static void	tcp_close_output(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
static void	tcp_output(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
static void	tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
static void	tcp_timer_handler(void *arg, mblk_t *mp, void *arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
/* Prototype for TCP functions */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
static void	tcp_random_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
int		tcp_random(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
static void	tcp_accept(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
static void	tcp_accept_swap(tcp_t *listener, tcp_t *acceptor,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
		    tcp_t *eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
static int	tcp_adapt_ire(tcp_t *tcp, mblk_t *ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
static in_port_t tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr,
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
   775
    int reuseaddr, boolean_t quick_connect, boolean_t bind_to_req_port_only,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
   776
    boolean_t user_specified);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
static void	tcp_closei_local(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
static void	tcp_close_detached(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
static boolean_t tcp_conn_con(tcp_t *tcp, uchar_t *iphdr, tcph_t *tcph,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
			mblk_t *idmp, mblk_t **defermp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
static void	tcp_connect(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
static void	tcp_connect_ipv4(tcp_t *tcp, mblk_t *mp, ipaddr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
		    in_port_t dstport, uint_t srcid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
static void	tcp_connect_ipv6(tcp_t *tcp, mblk_t *mp, in6_addr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
		    in_port_t dstport, uint32_t flowinfo, uint_t srcid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
		    uint32_t scope_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
static int	tcp_clean_death(tcp_t *tcp, int err, uint8_t tag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
static void	tcp_def_q_set(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
static void	tcp_disconnect(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
static char	*tcp_display(tcp_t *tcp, char *, char);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
static boolean_t tcp_eager_blowoff(tcp_t *listener, t_scalar_t seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
static void	tcp_eager_cleanup(tcp_t *listener, boolean_t q0_only);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
static void	tcp_eager_unlink(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
static void	tcp_err_ack(tcp_t *tcp, mblk_t *mp, int tlierr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
		    int unixerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
static void	tcp_err_ack_prim(tcp_t *tcp, mblk_t *mp, int primitive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
		    int tlierr, int unixerr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
static int	tcp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
static int	tcp_extra_priv_ports_add(queue_t *q, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
		    char *value, caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
static int	tcp_extra_priv_ports_del(queue_t *q, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
		    char *value, caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
static int	tcp_tpistate(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
static void	tcp_bind_hash_insert(tf_t *tf, tcp_t *tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
    int caller_holds_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
static void	tcp_bind_hash_remove(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
static tcp_t	*tcp_acceptor_hash_lookup(t_uscalar_t id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
void		tcp_acceptor_hash_insert(t_uscalar_t id, tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
static void	tcp_acceptor_hash_remove(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
static void	tcp_capability_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
static void	tcp_info_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
static void	tcp_addr_req(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
static void	tcp_addr_req_ipv6(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
static int	tcp_header_init_ipv4(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
static int	tcp_header_init_ipv6(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
int		tcp_init(tcp_t *tcp, queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
static int	tcp_init_values(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
static mblk_t	*tcp_ip_advise_mblk(void *addr, int addr_len, ipic_t **ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
static mblk_t	*tcp_ip_bind_mp(tcp_t *tcp, t_scalar_t bind_prim,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
		    t_scalar_t addr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
static void	tcp_ip_ire_mark_advice(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
static void	tcp_ip_notify(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
static mblk_t	*tcp_ire_mp(mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
static void	tcp_iss_init(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
static void	tcp_keepalive_killer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
static int	tcp_parse_options(tcph_t *tcph, tcp_opt_t *tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
static void	tcp_mss_set(tcp_t *tcp, uint32_t size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
static int	tcp_conprim_opt_process(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
		    int *do_disconnectp, int *t_errorp, int *sys_errorp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
static boolean_t tcp_allow_connopt_set(int level, int name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
int		tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
int		tcp_opt_get(queue_t *q, int level, int name, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
static int	tcp_opt_get_user(ipha_t *ipha, uchar_t *ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
int		tcp_opt_set(queue_t *q, uint_t optset_context, int level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
		    int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
		    uchar_t *outvalp, void *thisdg_attrs, cred_t *cr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
		    mblk_t *mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
static void	tcp_opt_reverse(tcp_t *tcp, ipha_t *ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
static int	tcp_opt_set_header(tcp_t *tcp, boolean_t checkonly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
		    uchar_t *ptr, uint_t len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
static int	tcp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
static boolean_t tcp_param_register(tcpparam_t *tcppa, int cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
static int	tcp_param_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
static int	tcp_param_set_aligned(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
static void	tcp_iss_key_init(uint8_t *phrase, int len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
static int	tcp_1948_phrase_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
static void	tcp_process_shrunk_swnd(tcp_t *tcp, uint32_t shrunk_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
static mblk_t	*tcp_reass(tcp_t *tcp, mblk_t *mp, uint32_t start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
static void	tcp_reass_elim_overlap(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
static void	tcp_reinit(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
static void	tcp_reinit_values(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
static void	tcp_report_item(mblk_t *mp, tcp_t *tcp, int hashval,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
		    tcp_t *thisstream, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
static uint_t	tcp_rcv_drain(queue_t *q, tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
static void	tcp_sack_rxmit(tcp_t *tcp, uint_t *flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
static boolean_t tcp_send_rst_chk(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
static void	tcp_ss_rexmit(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
static mblk_t	*tcp_rput_add_ancillary(tcp_t *tcp, mblk_t *mp, ip6_pkt_t *ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
static void	tcp_process_options(tcp_t *, tcph_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
static void	tcp_rput_common(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
static void	tcp_rsrv(queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
static int	tcp_rwnd_set(tcp_t *tcp, uint32_t rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
static int	tcp_snmp_state(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
static int	tcp_status_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
static int	tcp_bind_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
static int	tcp_listen_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
static int	tcp_conn_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
static int	tcp_acceptor_hash_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
static int	tcp_host_param_set(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
static int	tcp_host_param_set_ipv6(queue_t *q, mblk_t *mp, char *value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
		    caddr_t cp, cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
static int	tcp_host_param_report(queue_t *q, mblk_t *mp, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
		    cred_t *cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
static void	tcp_timer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
static void	tcp_timer_callback(void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
static in_port_t tcp_update_next_port(in_port_t port, boolean_t random);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
static in_port_t tcp_get_next_priv_port(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
static void	tcp_wput_sock(queue_t *q, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
void		tcp_wput_accept(queue_t *q, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
static void	tcp_wput_data(tcp_t *tcp, mblk_t *mp, boolean_t urgent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
static void	tcp_wput_flush(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
static void	tcp_wput_iocdata(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
static int	tcp_send(queue_t *q, tcp_t *tcp, const int mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
		    const int tcp_hdr_len, const int tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
		    const int num_sack_blk, int *usable, uint_t *snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
		    int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
		    const int mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
static int	tcp_multisend(queue_t *q, tcp_t *tcp, const int mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
		    const int tcp_hdr_len, const int tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		    const int num_sack_blk, int *usable, uint_t *snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
		    int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
		    const int mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
static void	tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
		    int num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
static void	tcp_wsrv(queue_t *q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
static int	tcp_xmit_end(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
void		tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
static mblk_t	*tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
		    int32_t *offset, mblk_t **end_mp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
		    boolean_t sendall, uint32_t *seg_len, boolean_t rexmit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
static void	tcp_ack_timer(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
static mblk_t	*tcp_ack_mp(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
static void	tcp_xmit_early_reset(char *str, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
		    uint32_t seq, uint32_t ack, int ctl, uint_t ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
static void	tcp_xmit_ctl(char *str, tcp_t *tcp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
		    uint32_t ack, int ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
static tcp_hsp_t *tcp_hsp_lookup(ipaddr_t addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
static tcp_hsp_t *tcp_hsp_lookup_ipv6(in6_addr_t *addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
static int	setmaxps(queue_t *q, int maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
static void	tcp_set_rto(tcp_t *, time_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
static boolean_t tcp_check_policy(tcp_t *, mblk_t *, ipha_t *, ip6_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
		    boolean_t, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
static void	tcp_icmp_error_ipv6(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
		    boolean_t ipsec_mctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
static boolean_t tcp_cmpbuf(void *a, uint_t alen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
		    boolean_t b_valid, void *b, uint_t blen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
static boolean_t tcp_allocbuf(void **dstp, uint_t *dstlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
		    boolean_t src_valid, void *src, uint_t srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
static void	tcp_savebuf(void **dstp, uint_t *dstlenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
		    boolean_t src_valid, void *src, uint_t srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
static mblk_t	*tcp_setsockopt_mp(int level, int cmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
		    char *opt, int optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
static int	tcp_pkt_set(uchar_t *, uint_t, uchar_t **, uint_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
static int	tcp_build_hdrs(queue_t *, tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
static void	tcp_time_wait_processing(tcp_t *tcp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
		    uint32_t seg_seq, uint32_t seg_ack, int seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
		    tcph_t *tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
boolean_t	tcp_paws_check(tcp_t *tcp, tcph_t *tcph, tcp_opt_t *tcpoptp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
boolean_t	tcp_reserved_port_add(int, in_port_t *, in_port_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
boolean_t	tcp_reserved_port_del(in_port_t, in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
boolean_t	tcp_reserved_port_check(in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
static tcp_t	*tcp_alloc_temp_tcp(in_port_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
static int	tcp_reserved_port_list(queue_t *, mblk_t *, caddr_t, cred_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
static mblk_t	*tcp_mdt_info_mp(mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
static void	tcp_mdt_update(tcp_t *, ill_mdt_capab_t *, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
static int	tcp_mdt_add_attrs(multidata_t *, const mblk_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
		    const boolean_t, const uint32_t, const uint32_t,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
		    const uint32_t, const uint32_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
static void	tcp_multisend_data(tcp_t *, ire_t *, const ill_t *, mblk_t *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
		    const uint_t, const uint_t, boolean_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
static void	tcp_send_data(tcp_t *, queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
extern mblk_t	*tcp_timermp_alloc(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
extern void	tcp_timermp_free(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
static void	tcp_timer_free(tcp_t *tcp, mblk_t *mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
static void	tcp_stop_lingering(tcp_t *tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
static void	tcp_close_linger_timeout(void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
void		tcp_ddi_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
void		tcp_ddi_destroy(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
static void	tcp_kstat_init(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
static void	tcp_kstat_fini(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
static int	tcp_kstat_update(kstat_t *kp, int rw);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
void		tcp_reinput(conn_t *connp, mblk_t *mp, squeue_t *sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
static int	tcp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
			tcph_t *tcph, uint_t ipvers, mblk_t *idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
static int	tcp_conn_create_v4(conn_t *lconnp, conn_t *connp, ipha_t *ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
			tcph_t *tcph, mblk_t *idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
static squeue_func_t tcp_squeue_switch(int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
static int	tcp_open(queue_t *, dev_t *, int, int, cred_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
static int	tcp_close(queue_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
static int	tcpclose_accept(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
static int	tcp_modclose(queue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
static void	tcp_wput_mod(queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
static void	tcp_squeue_add(squeue_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
static boolean_t tcp_zcopy_check(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
static void	tcp_zcopy_notify(tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
static mblk_t	*tcp_zcopy_disable(tcp_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
static mblk_t	*tcp_zcopy_backoff(tcp_t *, mblk_t *, int);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
static void	tcp_ire_ill_check(tcp_t *, ire_t *, ill_t *, boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
 * Routines related to the TCP_IOC_ABORT_CONN ioctl command.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
 * TCP_IOC_ABORT_CONN is a non-transparent ioctl command used for aborting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
 * TCP connections. To invoke this ioctl, a tcp_ioc_abort_conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
 * (defined in tcp.h) needs to be filled in and passed into the kernel
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
 * via an I_STR ioctl command (see streamio(7I)). The tcp_ioc_abort_conn_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
 * structure contains the four-tuple of a TCP connection and a range of TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
 * states (specified by ac_start and ac_end). The use of wildcard addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
 * and ports is allowed. Connections with a matching four tuple and a state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
 * within the specified range will be aborted. The valid states for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
 * ac_start and ac_end fields are in the range TCPS_SYN_SENT to TCPS_TIME_WAIT,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
 * inclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
 * An application which has its connection aborted by this ioctl will receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
 * an error that is dependent on the connection state at the time of the abort.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
 * If the connection state is < TCPS_TIME_WAIT, an application should behave as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
 * though a RST packet has been received.  If the connection state is equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
 * TCPS_TIME_WAIT, the 2MSL timeout will immediately be canceled by the kernel
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
 * and all resources associated with the connection will be freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
static mblk_t	*tcp_ioctl_abort_build_msg(tcp_ioc_abort_conn_t *, tcp_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
static void	tcp_ioctl_abort_dump(tcp_ioc_abort_conn_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
static void	tcp_ioctl_abort_handler(tcp_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
static int	tcp_ioctl_abort(tcp_ioc_abort_conn_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
static void	tcp_ioctl_abort_conn(queue_t *, mblk_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
static int	tcp_ioctl_abort_bucket(tcp_ioc_abort_conn_t *, int, int *,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
    boolean_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
static struct module_info tcp_rinfo =  {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1013
	TCP_MOD_ID, TCP_MOD_NAME, 0, INFPSZ, TCP_RECV_HIWATER, TCP_RECV_LOWATER
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
static struct module_info tcp_winfo =  {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1017
	TCP_MOD_ID, TCP_MOD_NAME, 0, INFPSZ, 127, 16
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
 * Entry points for TCP as a module. It only allows SNMP requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
 * to pass through.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
struct qinit tcp_mod_rinit = {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1025
	(pfi_t)putnext, NULL, tcp_open, ip_snmpmod_close, NULL, &tcp_rinfo,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
struct qinit tcp_mod_winit = {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1029
	(pfi_t)ip_snmpmod_wput, NULL, tcp_open, ip_snmpmod_close, NULL,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1030
	&tcp_rinfo
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
 * Entry points for TCP as a device. The normal case which supports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
 * the TCP functionality.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
struct qinit tcp_rinit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
	NULL, (pfi_t)tcp_rsrv, tcp_open, tcp_close, NULL, &tcp_rinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
struct qinit tcp_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
	(pfi_t)tcp_wput, (pfi_t)tcp_wsrv, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
/* Initial entry point for TCP in socket mode. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
struct qinit tcp_sock_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
	(pfi_t)tcp_wput_sock, (pfi_t)tcp_wsrv, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
 * Entry points for TCP as a acceptor STREAM opened by sockfs when doing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
 * an accept. Avoid allocating data structures since eager has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
 * been created.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
struct qinit tcp_acceptor_rinit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
	NULL, (pfi_t)tcp_rsrv, NULL, tcpclose_accept, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
struct qinit tcp_acceptor_winit = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
	(pfi_t)tcp_wput_accept, NULL, NULL, NULL, NULL, &tcp_winfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1063
/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1064
 * Entry points for TCP loopback (read side only)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1065
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1066
struct qinit tcp_loopback_rinit = {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1067
	(pfi_t)0, (pfi_t)tcp_rsrv, tcp_open, tcp_close, (pfi_t)0,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1068
	&tcp_rinfo, NULL, tcp_fuse_rrw, tcp_fuse_rinfop, STRUIOT_STANDARD
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1069
};
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1070
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
struct streamtab tcpinfo = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
	&tcp_rinit, &tcp_winit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
extern squeue_func_t tcp_squeue_wput_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
extern squeue_func_t tcp_squeue_timer_proc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
/* Protected by tcp_g_q_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
static queue_t	*tcp_g_q;	/* Default queue used during detached closes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
kmutex_t tcp_g_q_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
/* Protected by tcp_hsp_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
 * XXX The host param mechanism should go away and instead we should use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
 * the metrics associated with the routes to determine the default sndspace
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
 * and rcvspace.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
static tcp_hsp_t	**tcp_hsp_hash;	/* Hash table for HSPs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
krwlock_t tcp_hsp_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
 * Extra privileged ports. In host byte order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
 * Protected by tcp_epriv_port_lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
#define	TCP_NUM_EPRIV_PORTS	64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
static int	tcp_g_num_epriv_ports = TCP_NUM_EPRIV_PORTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
static uint16_t	tcp_g_epriv_ports[TCP_NUM_EPRIV_PORTS] = { 2049, 4045 };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
kmutex_t tcp_epriv_port_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
 * The smallest anonymous port in the priviledged port range which TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
 * looks for free port.  Use in the option TCP_ANONPRIVBIND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
static in_port_t tcp_min_anonpriv_port = 512;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
/* Only modified during _init and _fini thus no locking is needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
static caddr_t	tcp_g_nd;	/* Head of 'named dispatch' variable list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
/* Hint not protected by any lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
static uint_t	tcp_next_port_to_try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
/* TCP bind hash list - all tcp_t with state >= BOUND. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
static tf_t	tcp_bind_fanout[TCP_BIND_FANOUT_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
/* TCP queue hash list - all tcp_t in case they will be an acceptor. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
static tf_t	tcp_acceptor_fanout[TCP_FANOUT_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
 * TCP has a private interface for other kernel modules to reserve a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
 * port range for them to use.  Once reserved, TCP will not use any ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
 * in the range.  This interface relies on the TCP_EXCLBIND feature.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
 * the semantics of TCP_EXCLBIND is changed, implementation of this interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
 * has to be verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
 * There can be TCP_RESERVED_PORTS_ARRAY_MAX_SIZE port ranges.  Each port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
 * range can cover at most TCP_RESERVED_PORTS_RANGE_MAX ports.  A port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
 * range is [port a, port b] inclusive.  And each port range is between
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
 * TCP_LOWESET_RESERVED_PORT and TCP_LARGEST_RESERVED_PORT inclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
 * Note that the default anonymous port range starts from 32768.  There is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
 * no port "collision" between that and the reserved port range.  If there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
 * is port collision (because the default smallest anonymous port is lowered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
 * or some apps specifically bind to ports in the reserved port range), the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
 * system may not be able to reserve a port range even there are enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
 * unbound ports as a reserved port range contains consecutive ports .
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
#define	TCP_RESERVED_PORTS_ARRAY_MAX_SIZE	5
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
#define	TCP_RESERVED_PORTS_RANGE_MAX		1000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
#define	TCP_SMALLEST_RESERVED_PORT		10240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
#define	TCP_LARGEST_RESERVED_PORT		20480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
/* Structure to represent those reserved port ranges. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
typedef struct tcp_rport_s {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
	in_port_t	lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
	in_port_t	hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
	tcp_t		**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
} tcp_rport_t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
/* The reserved port array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
static tcp_rport_t tcp_reserved_port[TCP_RESERVED_PORTS_ARRAY_MAX_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
/* Locks to protect the tcp_reserved_ports array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
static krwlock_t tcp_reserved_port_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
/* The number of ranges in the array. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
uint32_t tcp_reserved_port_array_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
 * MIB-2 stuff for SNMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
 * Note: tcpInErrs {tcp 15} is accumulated in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
mib2_tcp_t	tcp_mib;	/* SNMP fixed size info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
kstat_t		*tcp_mibkp;	/* kstat exporting tcp_mib data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
boolean_t tcp_icmp_source_quench = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
 * Following assumes TPI alignment requirements stay along 32 bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
 * boundaries
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
#define	ROUNDUP32(x) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
	(((x) + (sizeof (int32_t) - 1)) & ~(sizeof (int32_t) - 1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
/* Template for response to info request. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
static struct T_info_ack tcp_g_t_info_ack = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
	T_INFO_ACK,		/* PRIM_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
	0,			/* TSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
	T_INFINITE,		/* ETSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
	T_INVALID,		/* CDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
	T_INVALID,		/* DDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
	sizeof (sin_t),		/* ADDR_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
	0,			/* OPT_size - not initialized here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
	TIDUSZ,			/* TIDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
	T_COTS_ORD,		/* SERV_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
	TCPS_IDLE,		/* CURRENT_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
static struct T_info_ack tcp_g_t_info_ack_v6 = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
	T_INFO_ACK,		/* PRIM_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
	0,			/* TSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
	T_INFINITE,		/* ETSDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
	T_INVALID,		/* CDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
	T_INVALID,		/* DDATA_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
	sizeof (sin6_t),	/* ADDR_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
	0,			/* OPT_size - not initialized here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	TIDUSZ,		/* TIDU_size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
	T_COTS_ORD,		/* SERV_type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	TCPS_IDLE,		/* CURRENT_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
	(XPG4_1|EXPINLINE)	/* PROVIDER_flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
#define	MS	1L
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
#define	SECONDS	(1000 * MS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
#define	MINUTES	(60 * SECONDS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
#define	HOURS	(60 * MINUTES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
#define	DAYS	(24 * HOURS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
#define	PARAM_MAX (~(uint32_t)0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
/* Max size IP datagram is 64k - 1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
#define	TCP_MSS_MAX_IPV4 (IP_MAXPACKET - (sizeof (ipha_t) + sizeof (tcph_t)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
#define	TCP_MSS_MAX_IPV6 (IP_MAXPACKET - (sizeof (ip6_t) + sizeof (tcph_t)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
/* Max of the above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
#define	TCP_MSS_MAX	TCP_MSS_MAX_IPV4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
/* Largest TCP port number */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
#define	TCP_MAX_PORT	(64 * 1024 - 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
 * tcp_wroff_xtra is the extra space in front of TCP/IP header for link
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
 * layer header.  It has to be a multiple of 4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
static tcpparam_t tcp_wroff_xtra_param = { 0, 256, 32, "tcp_wroff_xtra" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
#define	tcp_wroff_xtra	tcp_wroff_xtra_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
 * All of these are alterable, within the min/max values given, at run time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
 * Note that the default value of "tcp_time_wait_interval" is four minutes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
 * per the TCP spec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
tcpparam_t	tcp_param_arr[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
 /*min		max		value		name */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
 { 1*SECONDS,	10*MINUTES,	1*MINUTES,	"tcp_time_wait_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
 { 1,		PARAM_MAX,	128,		"tcp_conn_req_max_q" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
 { 0,		PARAM_MAX,	1024,		"tcp_conn_req_max_q0" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
 { 1,		1024,		1,		"tcp_conn_req_min" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
 { 0*MS,	20*SECONDS,	0*MS,		"tcp_conn_grace_period" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
 { 128,		(1<<30),	1024*1024,	"tcp_cwnd_max" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
 { 0,		10,		0,		"tcp_debug" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
 { 1024,	(32*1024),	1024,		"tcp_smallest_nonpriv_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
 { 1*SECONDS,	PARAM_MAX,	3*MINUTES,	"tcp_ip_abort_cinterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
 { 1*SECONDS,	PARAM_MAX,	3*MINUTES,	"tcp_ip_abort_linterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
 { 500*MS,	PARAM_MAX,	8*MINUTES,	"tcp_ip_abort_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
 { 1*SECONDS,	PARAM_MAX,	10*SECONDS,	"tcp_ip_notify_cinterval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
 { 500*MS,	PARAM_MAX,	10*SECONDS,	"tcp_ip_notify_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
 { 1,		255,		64,		"tcp_ipv4_ttl"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
 { 10*SECONDS,	10*DAYS,	2*HOURS,	"tcp_keepalive_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
 { 0,		100,		10,		"tcp_maxpsz_multiplier" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
 { 1,		TCP_MSS_MAX_IPV4, 536,		"tcp_mss_def_ipv4"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
 { 1,		TCP_MSS_MAX_IPV4, TCP_MSS_MAX_IPV4, "tcp_mss_max_ipv4"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
 { 1,		TCP_MSS_MAX,	108,		"tcp_mss_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
 { 1,		(64*1024)-1,	(4*1024)-1,	"tcp_naglim_def"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
 { 1*MS,	20*SECONDS,	3*SECONDS,	"tcp_rexmit_interval_initial"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
 { 1*MS,	2*HOURS,	60*SECONDS,	"tcp_rexmit_interval_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
 { 1*MS,	2*HOURS,	400*MS,		"tcp_rexmit_interval_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
 { 1*MS,	1*MINUTES,	100*MS,		"tcp_deferred_ack_interval" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
 { 0,		16,		0,		"tcp_snd_lowat_fraction" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
 { 0,		128000,		0,		"tcp_sth_rcv_hiwat" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
 { 0,		128000,		0,		"tcp_sth_rcv_lowat" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
 { 1,		10000,		3,		"tcp_dupack_fast_retransmit" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
 { 0,		1,		0,		"tcp_ignore_path_mtu" },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
 { 1024,	TCP_MAX_PORT,	32*1024,	"tcp_smallest_anon_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
 { 1024,	TCP_MAX_PORT,	TCP_MAX_PORT,	"tcp_largest_anon_port"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
 { TCP_XMIT_LOWATER, (1<<30), TCP_XMIT_HIWATER,"tcp_xmit_hiwat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
 { TCP_XMIT_LOWATER, (1<<30), TCP_XMIT_LOWATER,"tcp_xmit_lowat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
 { TCP_RECV_LOWATER, (1<<30), TCP_RECV_HIWATER,"tcp_recv_hiwat"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
 { 1,		65536,		4,		"tcp_recv_hiwat_minmss"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
 { 1*SECONDS,	PARAM_MAX,	675*SECONDS,	"tcp_fin_wait_2_flush_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
 { 0,		TCP_MSS_MAX,	64,		"tcp_co_min"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
 { 8192,	(1<<30),	1024*1024,	"tcp_max_buf"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
 * Question:  What default value should I set for tcp_strong_iss?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
 { 0,		2,		1,		"tcp_strong_iss"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
 { 0,		65536,		20,		"tcp_rtt_updates"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
 { 0,		1,		1,		"tcp_wscale_always"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
 { 0,		1,		0,		"tcp_tstamp_always"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
 { 0,		1,		1,		"tcp_tstamp_if_wscale"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
 { 0*MS,	2*HOURS,	0*MS,		"tcp_rexmit_interval_extra"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
 { 0,		16,		2,		"tcp_deferred_acks_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
 { 1,		16384,		4,		"tcp_slow_start_after_idle"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
 { 1,		4,		4,		"tcp_slow_start_initial"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
 { 10*MS,	50*MS,		20*MS,		"tcp_co_timer_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
 { 0,		2,		2,		"tcp_sack_permitted"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
 { 0,		1,		0,		"tcp_trace"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
 { 0,		1,		1,		"tcp_compression_enabled"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
 { 0,		IPV6_MAX_HOPS,	IPV6_DEFAULT_HOPS,	"tcp_ipv6_hoplimit"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
 { 1,		TCP_MSS_MAX_IPV6, 1220,		"tcp_mss_def_ipv6"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
 { 1,		TCP_MSS_MAX_IPV6, TCP_MSS_MAX_IPV6, "tcp_mss_max_ipv6"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
 { 0,		1,		0,		"tcp_rev_src_routes"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
 { 10*MS,	500*MS,		50*MS,		"tcp_local_dack_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
 { 100*MS,	60*SECONDS,	1*SECONDS,	"tcp_ndd_get_info_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
 { 0,		16,		8,		"tcp_local_dacks_max"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
 { 0,		2,		1,		"tcp_ecn_permitted"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
 { 0,		1,		1,		"tcp_rst_sent_rate_enabled"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
 { 0,		PARAM_MAX,	40,		"tcp_rst_sent_rate"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
 { 0,		100*MS,		50*MS,		"tcp_push_timer_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
 { 0,		1,		0,		"tcp_use_smss_as_mss_opt"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
 { 0,		PARAM_MAX,	8*MINUTES,	"tcp_keepalive_abort_interval"},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
 * tcp_mdt_hdr_{head,tail}_min are the leading and trailing spaces of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
 * each header fragment in the header buffer.  Each parameter value has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
 * to be a multiple of 4 (32-bit aligned).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
static tcpparam_t tcp_mdt_head_param = { 32, 256, 32, "tcp_mdt_hdr_head_min" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
static tcpparam_t tcp_mdt_tail_param = { 0,  256, 32, "tcp_mdt_hdr_tail_min" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
#define	tcp_mdt_hdr_head_min	tcp_mdt_head_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
#define	tcp_mdt_hdr_tail_min	tcp_mdt_tail_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
 * tcp_mdt_max_pbufs is the upper limit value that tcp uses to figure out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
 * the maximum number of payload buffers associated per Multidata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
static tcpparam_t tcp_mdt_max_pbufs_param =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	{ 1, MULTIDATA_MAX_PBUFS, MULTIDATA_MAX_PBUFS, "tcp_mdt_max_pbufs" };
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
#define	tcp_mdt_max_pbufs	tcp_mdt_max_pbufs_param.tcp_param_val
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
/* Round up the value to the nearest mss. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
#define	MSS_ROUNDUP(value, mss)		((((value) - 1) / (mss) + 1) * (mss))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
 * Set ECN capable transport (ECT) code point in IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
 * Note that there are 2 ECT code points '01' and '10', which are called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
 * ECT(1) and ECT(0) respectively.  Here we follow the original ECT code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
 * point ECT(0) for TCP as described in RFC 2481.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
#define	SET_ECT(tcp, iph) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	if ((tcp)->tcp_ipversion == IPV4_VERSION) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
		/* We need to clear the code point first. */ \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
		((ipha_t *)(iph))->ipha_type_of_service &= 0xFC; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
		((ipha_t *)(iph))->ipha_type_of_service |= IPH_ECN_ECT0; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
	} else { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
		((ip6_t *)(iph))->ip6_vcf &= htonl(0xFFCFFFFF); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
		((ip6_t *)(iph))->ip6_vcf |= htonl(IPH_ECN_ECT0 << 20); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
 * The format argument to pass to tcp_display().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
 * DISP_PORT_ONLY means that the returned string has only port info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
 * DISP_ADDR_AND_PORT means that the returned string also contains the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
 * remote and local IP address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
#define	DISP_PORT_ONLY		1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
#define	DISP_ADDR_AND_PORT	2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
 * This controls the rate some ndd info report functions can be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
 * by non-priviledged users.  It stores the last time such info is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
 * requested.  When those report functions are called again, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
 * is checked with the current time and compare with the ndd param
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
 * tcp_ndd_get_info_interval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
static clock_t tcp_last_ndd_get_info_time = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
#define	NDD_TOO_QUICK_MSG \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
	"ndd get info rate too high for non-priviledged users, try again " \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	"later.\n"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
#define	NDD_OUT_OF_BUF_MSG	"<< Out of buffer >>\n"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
#define	IS_VMLOANED_MBLK(mp) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
	(((mp)->b_datap->db_struioflag & STRUIO_ZC) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
 * These two variables control the rate for TCP to generate RSTs in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
 * response to segments not belonging to any connections.  We limit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
 * TCP to sent out tcp_rst_sent_rate (ndd param) number of RSTs in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
 * each 1 second interval.  This is to protect TCP against DoS attack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
static clock_t tcp_last_rst_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
static uint32_t tcp_rst_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
/* The number of RST not sent because of the rate limit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
static uint32_t tcp_rst_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
/* Enable or disable b_cont M_MULTIDATA chaining for MDT. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
boolean_t tcp_mdt_chain = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
 * MDT threshold in the form of effective send MSS multiplier; we take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
 * the MDT path if the amount of unsent data exceeds the threshold value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
 * (default threshold is 1*SMSS).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
uint_t tcp_mdt_smss_threshold = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
uint32_t do_tcpzcopy = 1;		/* 0: disable, 1: enable, 2: force */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
 * Forces all connections to obey the value of the tcp_maxpsz_multiplier
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
 * tunable settable via NDD.  Otherwise, the per-connection behavior is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
 * determined dynamically during tcp_adapt_ire(), which is the default.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
boolean_t tcp_static_maxpsz = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
/* If set to 0, pick ephemeral port sequentially; otherwise randomly. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
uint32_t tcp_random_anon_port = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
 * If tcp_drop_ack_unsent_cnt is greater than 0, when TCP receives more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
 * than tcp_drop_ack_unsent_cnt number of ACKs which acknowledge unsent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
 * data, TCP will not respond with an ACK.  RFC 793 requires that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
 * TCP responds with an ACK for such a bogus ACK.  By not following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
 * the RFC, we prevent TCP from getting into an ACK storm if somehow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
 * an attacker successfully spoofs an acceptable segment to our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
 * peer; or when our peer is "confused."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
uint32_t tcp_drop_ack_unsent_cnt = 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
 * Hook functions to enable cluster networking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
 * On non-clustered systems these vectors must always be NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
void (*cl_inet_listen)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
			    uint8_t *laddrp, in_port_t lport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
void (*cl_inet_unlisten)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
			    uint8_t *laddrp, in_port_t lport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
void (*cl_inet_connect)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
			    uint8_t *laddrp, in_port_t lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
			    uint8_t *faddrp, in_port_t fport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
void (*cl_inet_disconnect)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
			    uint8_t *laddrp, in_port_t lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
			    uint8_t *faddrp, in_port_t fport) = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
 * The following are defined in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
extern int (*cl_inet_isclusterwide)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
				uint8_t *laddrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
extern uint32_t (*cl_inet_ipident)(uint8_t protocol, sa_family_t addr_family,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
				uint8_t *laddrp, uint8_t *faddrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
#define	CL_INET_CONNECT(tcp)		{			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
	if (cl_inet_connect != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
		/*						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
		 * Running in cluster mode - register active connection	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
		 * information						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
		 */							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
		if ((tcp)->tcp_ipversion == IPV4_VERSION) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
			if ((tcp)->tcp_ipha->ipha_src != 0) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
				(*cl_inet_connect)(IPPROTO_TCP, AF_INET,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
				    (uint8_t *)(&((tcp)->tcp_ipha->ipha_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
				    (uint8_t *)(&((tcp)->tcp_ipha->ipha_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
			if (!IN6_IS_ADDR_UNSPECIFIED(			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
			    &(tcp)->tcp_ip6h->ip6_src)) {\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
				(*cl_inet_connect)(IPPROTO_TCP, AF_INET6,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
				    (uint8_t *)(&((tcp)->tcp_ip6h->ip6_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
				    (uint8_t *)(&((tcp)->tcp_ip6h->ip6_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
#define	CL_INET_DISCONNECT(tcp)	{				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
	if (cl_inet_disconnect != NULL) {				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
		/*							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
		 * Running in cluster mode - deregister active		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
		 * connection information				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
		 */							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
		if ((tcp)->tcp_ipversion == IPV4_VERSION) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
			if ((tcp)->tcp_ip_src != 0) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
				(*cl_inet_disconnect)(IPPROTO_TCP,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
				    AF_INET,				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
				    (uint8_t *)(&((tcp)->tcp_ip_src)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
				    (uint8_t *)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
				    (&((tcp)->tcp_ipha->ipha_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
		} else {						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
			if (!IN6_IS_ADDR_UNSPECIFIED(			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
			    &(tcp)->tcp_ip_src_v6)) {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
				(*cl_inet_disconnect)(IPPROTO_TCP, AF_INET6,\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
				    (uint8_t *)(&((tcp)->tcp_ip_src_v6)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
				    (in_port_t)(tcp)->tcp_lport,	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
				    (uint8_t *)				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
				    (&((tcp)->tcp_ip6h->ip6_dst)),\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
				    (in_port_t)(tcp)->tcp_fport);	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
			}						\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
		}							\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
	}								\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
 * Cluster networking hook for traversing current connection list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
 * This routine is used to extract the current list of live connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
 * which must continue to to be dispatched to this node.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
int cl_tcp_walk_list(int (*callback)(cl_tcp_info_t *, void *), void *arg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
 * Figure out the value of window scale opton.  Note that the rwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
 * ASSUMED to be rounded up to the nearest MSS before the calculation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
 * We cannot find the scale value and then do a round up of tcp_rwnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
 * because the scale value may not be correct after that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
 * Set the compiler flag to make this function inline.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
tcp_set_ws_value(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
	uint32_t rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
	for (i = 0; rwnd > TCP_MAXWIN && i < TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	    i++, rwnd >>= 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
		;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
	tcp->tcp_rcv_ws = i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
 * Remove a connection from the list of detached TIME_WAIT connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
tcp_time_wait_remove(tcp_t *tcp, tcp_squeue_priv_t *tcp_time_wait)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
	boolean_t	locked = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
	if (tcp_time_wait == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
		tcp_time_wait = *((tcp_squeue_priv_t **)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
		    squeue_getprivate(tcp->tcp_connp->conn_sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
		mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
		locked = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
	if (tcp->tcp_time_wait_expire == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
		if (locked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
			mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
	ASSERT(tcp->tcp_state == TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
	if (tcp == tcp_time_wait->tcp_time_wait_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
		tcp_time_wait->tcp_time_wait_head = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
		if (tcp_time_wait->tcp_time_wait_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
			tcp_time_wait->tcp_time_wait_head->tcp_time_wait_prev =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
			    NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
			tcp_time_wait->tcp_time_wait_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
	} else if (tcp == tcp_time_wait->tcp_time_wait_tail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
		ASSERT(tcp != tcp_time_wait->tcp_time_wait_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
		tcp_time_wait->tcp_time_wait_tail = tcp->tcp_time_wait_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
		ASSERT(tcp_time_wait->tcp_time_wait_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		tcp_time_wait->tcp_time_wait_tail->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
		ASSERT(tcp->tcp_time_wait_prev->tcp_time_wait_next == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
		ASSERT(tcp->tcp_time_wait_next->tcp_time_wait_prev == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
		tcp->tcp_time_wait_prev->tcp_time_wait_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
		    tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
		tcp->tcp_time_wait_next->tcp_time_wait_prev =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
		    tcp->tcp_time_wait_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
	tcp->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
	tcp->tcp_time_wait_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
	tcp->tcp_time_wait_expire = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
	if (locked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
		mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
 * Add a connection to the list of detached TIME_WAIT connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
 * and set its time to expire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
tcp_time_wait_append(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
	tcp_squeue_priv_t *tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
	    *((tcp_squeue_priv_t **)squeue_getprivate(tcp->tcp_connp->conn_sqp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
		SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
	/* Freed above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
	ASSERT(tcp->tcp_timer_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
	ASSERT(tcp->tcp_ack_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
	/* must have happened at the time of detaching the tcp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	ASSERT(tcp->tcp_ptpahn == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
	ASSERT(tcp->tcp_flow_stopped == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
	ASSERT(tcp->tcp_time_wait_expire == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
	tcp->tcp_time_wait_expire = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
	 * The value computed below in tcp->tcp_time_wait_expire may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
	 * appear negative or wrap around. That is ok since our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
	 * interest is only in the difference between the current lbolt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
	 * value and tcp->tcp_time_wait_expire. But the value should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
	 * be zero, since it means the tcp is not in the TIME_WAIT list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	 * The corresponding comparison in tcp_time_wait_collector() uses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	 * modular arithmetic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
	tcp->tcp_time_wait_expire +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
	    drv_usectohz(tcp_time_wait_interval * 1000);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
	if (tcp->tcp_time_wait_expire == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
		tcp->tcp_time_wait_expire = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
	ASSERT(tcp->tcp_state == TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
	TCP_DBGSTAT(tcp_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
	if (tcp_time_wait->tcp_time_wait_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
		ASSERT(tcp_time_wait->tcp_time_wait_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
		tcp_time_wait->tcp_time_wait_head = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
		ASSERT(tcp_time_wait->tcp_time_wait_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
		ASSERT(tcp_time_wait->tcp_time_wait_tail->tcp_state ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
		    TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
		tcp_time_wait->tcp_time_wait_tail->tcp_time_wait_next = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
		tcp->tcp_time_wait_prev = tcp_time_wait->tcp_time_wait_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
	tcp_time_wait->tcp_time_wait_tail = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
tcp_timewait_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	if (tcp->tcp_state == TCPS_CLOSED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
	ASSERT(!tcp->tcp_listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
	TCP_STAT(tcp_time_wait_reap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
	ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
	 * Because they have no upstream client to rebind or tcp_close()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
	 * them later, we axe the connection here and now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
	tcp_close_detached(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
tcp_cleanup(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
	char		*tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
	int		tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
	int		tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
	tcp_sack_info_t	*tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
	tcp_free(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
	conn_delete_ire(connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
	if (connp->conn_flags & IPCL_TCPCONN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
		if (connp->conn_latch != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
			IPLATCH_REFRELE(connp->conn_latch);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
		if (connp->conn_policy != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
			IPPH_REFRELE(connp->conn_policy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
	 * Since we will bzero the entire structure, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
	 * remove it and reinsert it in global hash list. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
	 * know the walkers can't get to this conn because we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
	 * had set CONDEMNED flag earlier and checked reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
	 * under conn_lock so walker won't pick it and when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
	 * go the ipcl_globalhash_remove() below, no walker
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
	 * can get to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
	ipcl_globalhash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
	/* Save some state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
	mp = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
	tcp_sack_info = tcp->tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
	tcp_iphc = tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
	tcp_iphc_len = tcp->tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
	tcp_hdr_grown = tcp->tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
	bzero(connp, sizeof (conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
	bzero(tcp, sizeof (tcp_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	/* restore the state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	tcp->tcp_timercache = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
	tcp->tcp_sack_info = tcp_sack_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
	tcp->tcp_iphc = tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
	tcp->tcp_iphc_len = tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
	tcp->tcp_hdr_grown = tcp_hdr_grown;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	tcp->tcp_connp = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
	connp->conn_tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1721
	connp->conn_flags = IPCL_TCPCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1722
	connp->conn_state_flags = CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1723
	connp->conn_ulp = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1724
	connp->conn_ref = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1726
	ipcl_globalhash_insert(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1727
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1729
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1730
 * Blows away all tcps whose TIME_WAIT has expired. List traversal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1731
 * is done forwards from the head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1732
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1733
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1734
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1735
tcp_time_wait_collector(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1736
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1737
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1738
	clock_t now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1739
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1740
	conn_t *connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1741
	kmutex_t *lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1743
	squeue_t *sqp = (squeue_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1744
	tcp_squeue_priv_t *tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1745
	    *((tcp_squeue_priv_t **)squeue_getprivate(sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1747
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1748
	tcp_time_wait->tcp_time_wait_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1749
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1750
	if (tcp_time_wait->tcp_free_list != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1751
	    tcp_time_wait->tcp_free_list->tcp_in_free_list == B_TRUE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1752
		TCP_STAT(tcp_freelist_cleanup);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1753
		while ((tcp = tcp_time_wait->tcp_free_list) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1754
			tcp_time_wait->tcp_free_list = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1755
			CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1756
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1757
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1759
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1760
	 * In order to reap time waits reliably, we should use a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1761
	 * source of time that is not adjustable by the user -- hence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1762
	 * the call to ddi_get_lbolt().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1763
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1764
	now = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1765
	while ((tcp = tcp_time_wait->tcp_time_wait_head) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1766
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1767
		 * Compare times using modular arithmetic, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1768
		 * lbolt can wrapover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1769
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1770
		if ((now - tcp->tcp_time_wait_expire) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1771
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1772
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1774
		tcp_time_wait_remove(tcp, tcp_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1775
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1776
		connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1777
		ASSERT(connp->conn_fanout != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1778
		lock = &connp->conn_fanout->connf_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1779
		/*
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1780
		 * This is essentially a TW reclaim fast path optimization for
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1781
		 * performance where the timewait collector checks under the
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1782
		 * fanout lock (so that no one else can get access to the
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1783
		 * conn_t) that the refcnt is 2 i.e. one for TCP and one for
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1784
		 * the classifier hash list. If ref count is indeed 2, we can
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1785
		 * just remove the conn under the fanout lock and avoid
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1786
		 * cleaning up the conn under the squeue, provided that
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1787
		 * clustering callbacks are not enabled. If clustering is
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1788
		 * enabled, we need to make the clustering callback before
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1789
		 * setting the CONDEMNED flag and after dropping all locks and
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1790
		 * so we forego this optimization and fall back to the slow
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1791
		 * path. Also please see the comments in tcp_closei_local
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1792
		 * regarding the refcnt logic.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1793
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1794
		 * Since we are holding the tcp_time_wait_lock, its better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1795
		 * not to block on the fanout_lock because other connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1796
		 * can't add themselves to time_wait list. So we do a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1797
		 * tryenter instead of mutex_enter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1798
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1799
		if (mutex_tryenter(lock)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1800
			mutex_enter(&connp->conn_lock);
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1801
			if ((connp->conn_ref == 2) &&
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
  1802
			    (cl_inet_disconnect == NULL)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1803
				ipcl_hash_remove_locked(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1804
				    connp->conn_fanout);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1805
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1806
				 * Set the CONDEMNED flag now itself so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1807
				 * the refcnt cannot increase due to any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1808
				 * walker. But we have still not cleaned up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1809
				 * conn_ire_cache. This is still ok since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1810
				 * we are going to clean it up in tcp_cleanup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1811
				 * immediately and any interface unplumb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1812
				 * thread will wait till the ire is blown away
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1813
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1814
				connp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1815
				mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1816
				mutex_exit(lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1817
				mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1818
				tcp_cleanup(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1819
				mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1820
				tcp->tcp_time_wait_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1821
				    tcp_time_wait->tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1822
				tcp_time_wait->tcp_free_list = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1823
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1824
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1825
				CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1826
				mutex_exit(lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1827
				mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1828
				mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1829
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1830
				 * We can reuse the closemp here since conn has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1831
				 * detached (otherwise we wouldn't even be in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1832
				 * time_wait list).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1833
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1834
				mp = &tcp->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1835
				squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1836
				    tcp_timewait_output, connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1837
				    SQTAG_TCP_TIMEWAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1838
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1839
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1840
			mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1841
			CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1842
			mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1843
			mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1844
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1845
			 * We can reuse the closemp here since conn has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1846
			 * detached (otherwise we wouldn't even be in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1847
			 * time_wait list).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1848
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1849
			mp = &tcp->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1850
			squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1851
			    tcp_timewait_output, connp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1852
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1853
		mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1854
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1856
	if (tcp_time_wait->tcp_free_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1857
		tcp_time_wait->tcp_free_list->tcp_in_free_list = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1859
	tcp_time_wait->tcp_time_wait_tid =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1860
	    timeout(tcp_time_wait_collector, sqp, TCP_TIME_WAIT_DELAY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1861
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1862
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1864
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1865
 * Reply to a clients T_CONN_RES TPI message. This function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1866
 * is used only for TLI/XTI listener. Sockfs sends T_CONN_RES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1867
 * on the acceptor STREAM and processed in tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1868
 * Read the block comment on top of tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1869
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1870
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1871
tcp_accept(tcp_t *listener, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1872
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1873
	tcp_t	*acceptor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1874
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1875
	tcp_t   *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1876
	struct T_conn_res	*tcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1877
	t_uscalar_t	acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1878
	t_scalar_t	seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1879
	mblk_t	*opt_mp = NULL;	/* T_OPTMGMT_REQ messages */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1880
	mblk_t	*ok_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1881
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1882
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1883
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1884
		tcp_err_ack(listener, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1885
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1886
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1887
	tcr = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1889
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1890
	 * Under ILP32 the stream head points tcr->ACCEPTOR_id at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1891
	 * read side queue of the streams device underneath us i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1892
	 * read side queue of 'ip'. Since we can't deference QUEUE_ptr we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1893
	 * look it up in the queue_hash.  Under LP64 it sends down the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1894
	 * minor_t of the accepting endpoint.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1895
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1896
	 * Once the acceptor/eager are modified (in tcp_accept_swap) the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1897
	 * fanout hash lock is held.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1898
	 * This prevents any thread from entering the acceptor queue from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1899
	 * below (since it has not been hard bound yet i.e. any inbound
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1900
	 * packets will arrive on the listener or default tcp queue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1901
	 * go through tcp_lookup).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1902
	 * The CONN_INC_REF will prevent the acceptor from closing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1903
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1904
	 * XXX It is still possible for a tli application to send down data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1905
	 * on the accepting stream while another thread calls t_accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1906
	 * This should not be a problem for well-behaved applications since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1907
	 * the T_OK_ACK is sent after the queue swapping is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1908
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1909
	 * If the accepting fd is the same as the listening fd, avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1910
	 * queue hash lookup since that will return an eager listener in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1911
	 * already established state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1912
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1913
	acceptor_id = tcr->ACCEPTOR_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1914
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1915
	if (listener->tcp_acceptor_id == acceptor_id) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1916
		eager = listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1917
		/* only count how many T_CONN_INDs so don't count q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1918
		if ((listener->tcp_conn_req_cnt_q != 1) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1919
		    (eager->tcp_conn_req_seqnum != tcr->SEQ_number)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1920
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1921
			tcp_err_ack(listener, mp, TBADF, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1922
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1923
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1924
		if (listener->tcp_conn_req_cnt_q0 != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1925
			/* Throw away all the eagers on q0. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1926
			tcp_eager_cleanup(listener, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1927
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1928
		if (listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1929
			listener->tcp_syn_defense = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1930
			if (listener->tcp_ip_addr_cache != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1931
				kmem_free(listener->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1932
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1933
				listener->tcp_ip_addr_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1934
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1935
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1936
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1937
		 * Transfer tcp_conn_req_max to the eager so that when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1938
		 * a disconnect occurs we can revert the endpoint to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1939
		 * listen state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1940
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1941
		eager->tcp_conn_req_max = listener->tcp_conn_req_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1942
		ASSERT(listener->tcp_conn_req_cnt_q0 == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1943
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1944
		 * Get a reference on the acceptor just like the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1945
		 * tcp_acceptor_hash_lookup below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1946
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1947
		acceptor = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1948
		CONN_INC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1949
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1950
		acceptor = tcp_acceptor_hash_lookup(acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1951
		if (acceptor == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1952
			if (listener->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  1953
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1954
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1955
				    "tcp_accept: did not find acceptor 0x%x\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1956
				    acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1957
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1958
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1959
			tcp_err_ack(listener, mp, TPROVMISMATCH, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1960
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1961
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1962
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1963
		 * Verify acceptor state. The acceptable states for an acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1964
		 * include TCPS_IDLE and TCPS_BOUND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1965
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1966
		switch (acceptor->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1967
		case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1968
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1969
		case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1970
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1971
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1972
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1973
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1974
			tcp_err_ack(listener, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1975
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1976
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1977
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1978
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1979
	/* The listener must be in TCPS_LISTEN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1980
	if (listener->tcp_state != TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1981
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1982
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1983
		tcp_err_ack(listener, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1984
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1985
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1987
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1988
	 * Rendezvous with an eager connection request packet hanging off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1989
	 * 'tcp' that has the 'seqnum' tag.  We tagged the detached open
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1990
	 * tcp structure when the connection packet arrived in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1991
	 * tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1992
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1993
	seqnum = tcr->SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1994
	eager = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1995
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1996
		eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1997
		if (eager == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1998
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1999
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2000
			tcp_err_ack(listener, mp, TBADSEQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2001
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2002
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2003
	} while (eager->tcp_conn_req_seqnum != seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2004
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2006
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2007
	 * At this point, both acceptor and listener have 2 ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2008
	 * that they begin with. Acceptor has one additional ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2009
	 * we placed in lookup while listener has 3 additional
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2010
	 * ref for being behind the squeue (tcp_accept() is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2011
	 * done on listener's squeue); being in classifier hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2012
	 * and eager's ref on listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2013
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2014
	ASSERT(listener->tcp_connp->conn_ref >= 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2015
	ASSERT(acceptor->tcp_connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2017
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2018
	 * The eager at this point is set in its own squeue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2019
	 * could easily have been killed (tcp_accept_finish will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2020
	 * deal with that) because of a TH_RST so we can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2021
	 * ASSERT for a single ref.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2022
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2023
	ASSERT(eager->tcp_connp->conn_ref >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2025
	/* Pre allocate the stroptions mblk also */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2026
	opt_mp = allocb(sizeof (struct stroptions), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2027
	if (opt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2028
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2029
		CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2030
		tcp_err_ack(listener, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2031
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2032
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2033
	DB_TYPE(opt_mp) = M_SETOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2034
	opt_mp->b_wptr += sizeof (struct stroptions);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2035
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2036
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2037
	 * Prepare for inheriting IPV6_BOUND_IF and IPV6_RECVPKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2038
	 * from listener to acceptor. The message is chained on opt_mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2039
	 * which will be sent onto eager's squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2040
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2041
	if (listener->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2042
		/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2043
		mp1 = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2044
		    IPV6_BOUND_IF, (char *)&listener->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2045
		    sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2046
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2047
			linkb(opt_mp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2048
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2049
	if (listener->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2050
		uint_t on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2052
		/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2053
		mp1 = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2054
		    IPV6_RECVPKTINFO, (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2055
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2056
			linkb(opt_mp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2057
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2059
	/* Re-use mp1 to hold a copy of mp, in case reallocb fails */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2060
	if ((mp1 = copymsg(mp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2061
		CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2062
		CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2063
		freemsg(opt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2064
		tcp_err_ack(listener, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2065
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2066
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2068
	tcr = (struct T_conn_res *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2069
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2070
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2071
	 * This is an expanded version of mi_tpi_ok_ack_alloc()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2072
	 * which allocates a larger mblk and appends the new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2073
	 * local address to the ok_ack.  The address is copied by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2074
	 * soaccept() for getsockname().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2076
	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2077
		int extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2079
		extra = (eager->tcp_family == AF_INET) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2080
		    sizeof (sin_t) : sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2082
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2083
		 * Try to re-use mp, if possible.  Otherwise, allocate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2084
		 * an mblk and return it as ok_mp.  In any case, mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2085
		 * is no longer usable upon return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2086
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2087
		if ((ok_mp = mi_tpi_ok_ack_alloc_extra(mp, extra)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2088
			CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2089
			CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2090
			freemsg(opt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2091
			/* Original mp has been freed by now, so use mp1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2092
			tcp_err_ack(listener, mp1, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2093
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2094
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2096
		mp = NULL;	/* We should never use mp after this point */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2097
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2098
		switch (extra) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2099
		case sizeof (sin_t): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2100
				sin_t *sin = (sin_t *)ok_mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2102
				ok_mp->b_wptr += extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2103
				sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2104
				sin->sin_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2105
				sin->sin_addr.s_addr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2106
				    eager->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2107
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2108
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2109
		case sizeof (sin6_t): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2110
				sin6_t *sin6 = (sin6_t *)ok_mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2112
				ok_mp->b_wptr += extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2113
				sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2114
				sin6->sin6_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2115
				if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2116
					sin6->sin6_flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2117
					IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2118
					    eager->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2119
					    &sin6->sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2120
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2121
					ASSERT(eager->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2122
					sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2123
					    eager->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2124
					    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2125
					sin6->sin6_addr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2126
					    eager->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2127
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2128
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2129
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2130
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2131
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2132
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2133
		ASSERT(ok_mp->b_wptr <= ok_mp->b_datap->db_lim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2134
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2136
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2137
	 * If there are no options we know that the T_CONN_RES will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2138
	 * succeed. However, we can't send the T_OK_ACK upstream until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2139
	 * the tcp_accept_swap is done since it would be dangerous to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2140
	 * let the application start using the new fd prior to the swap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2141
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2142
	tcp_accept_swap(listener, acceptor, eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2144
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2145
	 * tcp_accept_swap unlinks eager from listener but does not drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2146
	 * the eager's reference on the listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2147
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2148
	ASSERT(eager->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2149
	ASSERT(listener->tcp_connp->conn_ref >= 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2150
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2151
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2152
	 * The eager is now associated with its own queue. Insert in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2153
	 * the hash so that the connection can be reused for a future
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2154
	 * T_CONN_RES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2155
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2156
	tcp_acceptor_hash_insert(acceptor_id, eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2158
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2159
	 * We now do the processing of options with T_CONN_RES.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2160
	 * We delay till now since we wanted to have queue to pass to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2161
	 * option processing routines that points back to the right
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2162
	 * instance structure which does not happen until after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2163
	 * tcp_accept_swap().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2164
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2165
	 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2166
	 * The sanity of the logic here assumes that whatever options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2167
	 * are appropriate to inherit from listner=>eager are done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2168
	 * before this point, and whatever were to be overridden (or not)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2169
	 * in transfer logic from eager=>acceptor in tcp_accept_swap().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2170
	 * [ Warning: acceptor endpoint can have T_OPTMGMT_REQ done to it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2171
	 *   before its ACCEPTOR_id comes down in T_CONN_RES ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2172
	 * This may not be true at this point in time but can be fixed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2173
	 * independently. This option processing code starts with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2174
	 * the instantiated acceptor instance and the final queue at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2175
	 * this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2176
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2178
	if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2179
		/* Options to process */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2180
		int t_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2181
		int sys_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2182
		int do_disconnect = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2183
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2184
		if (tcp_conprim_opt_process(eager, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2185
		    &do_disconnect, &t_error, &sys_error) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2186
			eager->tcp_accept_error = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2187
			if (do_disconnect) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2188
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2189
				 * An option failed which does not allow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2190
				 * connection to be accepted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2191
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2192
				 * We allow T_CONN_RES to succeed and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2193
				 * put a T_DISCON_IND on the eager queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2194
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2195
				ASSERT(t_error == 0 && sys_error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2196
				eager->tcp_send_discon_ind = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2197
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2198
				ASSERT(t_error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2199
				freemsg(ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2200
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2201
				 * Original mp was either freed or set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2202
				 * to ok_mp above, so use mp1 instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2203
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2204
				tcp_err_ack(listener, mp1, t_error, sys_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2205
				goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2206
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2207
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2208
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2209
		 * Most likely success in setting options (except if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2210
		 * eager->tcp_send_discon_ind set).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2211
		 * mp1 option buffer represented by OPT_length/offset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2212
		 * potentially modified and contains results of setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2213
		 * options at this point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2214
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2215
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2217
	/* We no longer need mp1, since all options processing has passed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2218
	freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2220
	putnext(listener->tcp_rq, ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2222
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2223
	if (listener->tcp_eager_prev_q0->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2224
		tcp_t	*tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2225
		mblk_t	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2227
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2228
		 * This path should not be executed if listener and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2229
		 * acceptor streams are the same.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2230
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2231
		ASSERT(listener != acceptor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2233
		tcp = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2234
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2235
		 * listener->tcp_eager_prev_q0 points to the TAIL of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2236
		 * deferred T_conn_ind queue. We need to get to the head of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2237
		 * the queue in order to send up T_conn_ind the same order as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2238
		 * how the 3WHS is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2239
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2240
		while (tcp != listener) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2241
			if (!tcp->tcp_eager_prev_q0->tcp_conn_def_q0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2242
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2243
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2244
				tcp = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2245
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2246
		ASSERT(tcp != listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2247
		conn_ind = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2248
		ASSERT(conn_ind != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2249
		tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2251
		/* Move from q0 to q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2252
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2253
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2254
		listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2255
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2256
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2257
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2258
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2259
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2260
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2261
		tcp->tcp_conn_def_q0 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2263
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2264
		 * Insert at end of the queue because sockfs sends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2265
		 * down T_CONN_RES in chronological order. Leaving
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2266
		 * the older conn indications at front of the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2267
		 * helps reducing search time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2268
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2269
		tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2270
		if (tail != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2271
			tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2272
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2273
			listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2274
		listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2275
		tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2276
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2277
		putnext(tcp->tcp_rq, conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2278
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2279
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2280
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2282
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2283
	 * Done with the acceptor - free it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2284
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2285
	 * Note: from this point on, no access to listener should be made
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2286
	 * as listener can be equal to acceptor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2287
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2288
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2289
	ASSERT(acceptor->tcp_detached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2290
	acceptor->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2291
	acceptor->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2292
	(void) tcp_clean_death(acceptor, 0, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2293
	CONN_DEC_REF(acceptor->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2295
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2296
	 * In case we already received a FIN we have to make tcp_rput send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2297
	 * the ordrel_ind. This will also send up a window update if the window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2298
	 * has opened up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2299
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2300
	 * In the normal case of a successful connection acceptance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2301
	 * we give the O_T_BIND_REQ to the read side put procedure as an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2302
	 * indication that this was just accepted. This tells tcp_rput to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2303
	 * pass up any data queued in tcp_rcv_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2304
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2305
	 * In the fringe case where options sent with T_CONN_RES failed and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2306
	 * we required, we would be indicating a T_DISCON_IND to blow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2307
	 * away this connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2308
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2309
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2310
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2311
	 * XXX: we currently have a problem if XTI application closes the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2312
	 * acceptor stream in between. This problem exists in on10-gate also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2313
	 * and is well know but nothing can be done short of major rewrite
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2314
	 * to fix it. Now it is possible to take care of it by assigning TLI/XTI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2315
	 * eager same squeue as listener (we can distinguish non socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2316
	 * listeners at the time of handling a SYN in tcp_conn_request)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2317
	 * and do most of the work that tcp_accept_finish does here itself
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2318
	 * and then get behind the acceptor squeue to access the acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2319
	 * queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2320
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2321
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2322
	 * We already have a ref on tcp so no need to do one before squeue_fill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2323
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2324
	squeue_fill(eager->tcp_connp->conn_sqp, opt_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2325
	    tcp_accept_finish, eager->tcp_connp, SQTAG_TCP_ACCEPT_FINISH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2326
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2328
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2329
 * Swap information between the eager and acceptor for a TLI/XTI client.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2330
 * The sockfs accept is done on the acceptor stream and control goes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2331
 * through tcp_wput_accept() and tcp_accept()/tcp_accept_swap() is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2332
 * called. In either case, both the eager and listener are in their own
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2333
 * perimeter (squeue) and the code has to deal with potential race.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2334
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2335
 * See the block comment on top of tcp_accept() and tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2336
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2337
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2338
tcp_accept_swap(tcp_t *listener, tcp_t *acceptor, tcp_t *eager)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2339
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2340
	conn_t	*econnp, *aconnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2341
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2342
	ASSERT(eager->tcp_rq == listener->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2343
	ASSERT(eager->tcp_detached && !acceptor->tcp_detached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2344
	ASSERT(!eager->tcp_hard_bound);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2345
	ASSERT(!TCP_IS_SOCKET(acceptor));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2346
	ASSERT(!TCP_IS_SOCKET(eager));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2347
	ASSERT(!TCP_IS_SOCKET(listener));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2349
	acceptor->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2350
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2351
	 * To permit stream re-use by TLI/XTI, the eager needs a copy of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2352
	 * the acceptor id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2353
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2354
	eager->tcp_acceptor_id = acceptor->tcp_acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2356
	/* remove eager from listen list... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2357
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2358
	tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2359
	ASSERT(eager->tcp_eager_next_q == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2360
	    eager->tcp_eager_last_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2361
	ASSERT(eager->tcp_eager_next_q0 == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2362
	    eager->tcp_eager_prev_q0 == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2363
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2364
	eager->tcp_rq = acceptor->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2365
	eager->tcp_wq = acceptor->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2367
	econnp = eager->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2368
	aconnp = acceptor->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2370
	eager->tcp_rq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2371
	eager->tcp_wq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2372
	eager->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2374
	ASSERT(eager->tcp_ack_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2376
	econnp->conn_dev = aconnp->conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2377
	eager->tcp_cred = econnp->conn_cred = aconnp->conn_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2378
	econnp->conn_zoneid = aconnp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2379
	aconnp->conn_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2381
	/* Do the IPC initialization */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2382
	CONN_INC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2384
	econnp->conn_multicast_loop = aconnp->conn_multicast_loop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2385
	econnp->conn_af_isv6 = aconnp->conn_af_isv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2386
	econnp->conn_pkt_isv6 = aconnp->conn_pkt_isv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2387
	econnp->conn_ulp = aconnp->conn_ulp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2389
	/* Done with old IPC. Drop its ref on its connp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2390
	CONN_DEC_REF(aconnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2391
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2394
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2395
 * Adapt to the information, such as rtt and rtt_sd, provided from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2396
 * ire cached in conn_cache_ire. If no ire cached, do a ire lookup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2397
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2398
 * Checks for multicast and broadcast destination address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2399
 * Returns zero on failure; non-zero if ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2400
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2401
 * Note that the MSS calculation here is based on the info given in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2402
 * the IRE.  We do not do any calculation based on TCP options.  They
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2403
 * will be handled in tcp_rput_other() and tcp_rput_data() when TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2404
 * knows which options to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2405
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2406
 * Note on how TCP gets its parameters for a connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2407
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2408
 * When a tcp_t structure is allocated, it gets all the default parameters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2409
 * In tcp_adapt_ire(), it gets those metric parameters, like rtt, rtt_sd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2410
 * spipe, rpipe, ... from the route metrics.  Route metric overrides the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2411
 * default.  But if there is an associated tcp_host_param, it will override
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2412
 * the metrics.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2413
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2414
 * An incoming SYN with a multicast or broadcast destination address, is dropped
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2415
 * in 1 of 2 places.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2416
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2417
 * 1. If the packet was received over the wire it is dropped in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2418
 * ip_rput_process_broadcast()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2419
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2420
 * 2. If the packet was received through internal IP loopback, i.e. the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2421
 * was generated and received on the same machine, it is dropped in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2422
 * ip_wput_local()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2423
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2424
 * An incoming SYN with a multicast or broadcast source address is always
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2425
 * dropped in tcp_adapt_ire. The same logic in tcp_adapt_ire also serves to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2426
 * reject an attempt to connect to a broadcast or multicast (destination)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2427
 * address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2428
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2429
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2430
tcp_adapt_ire(tcp_t *tcp, mblk_t *ire_mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2431
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2432
	tcp_hsp_t	*hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2433
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2434
	ire_t		*sire = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2435
	iulp_t		*ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2436
	uint32_t	mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2437
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2438
	boolean_t	tcp_detached = TCP_IS_DETACHED(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2439
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2440
	boolean_t	ire_cacheable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2441
	zoneid_t	zoneid = connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2442
	ill_t		*ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2443
	boolean_t	incoming = (ire_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2445
	ASSERT(connp->conn_ire_cache == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2447
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2449
		if (CLASSD(tcp->tcp_connp->conn_rem)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2450
			BUMP_MIB(&ip_mib, ipInDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2451
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2452
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2454
		ire = ire_cache_lookup(tcp->tcp_connp->conn_rem, zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2455
		if (ire != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2456
			ire_cacheable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2457
			ire_uinfo = (ire_mp != NULL) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2458
			    &((ire_t *)ire_mp->b_rptr)->ire_uinfo:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2459
			    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2461
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2462
			if (ire_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2463
				ire = ire_ftable_lookup(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2464
				    tcp->tcp_connp->conn_rem,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2465
				    0, 0, 0, NULL, &sire, zoneid, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2466
				    (MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2467
				if (ire == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2468
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2469
				ire_uinfo = (sire != NULL) ? &sire->ire_uinfo :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2470
				    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2471
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2472
				ire = (ire_t *)ire_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2473
				ire_uinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2474
				    &((ire_t *)ire_mp->b_rptr)->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2475
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2476
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2477
		ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2478
		ASSERT(ire_uinfo != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2480
		if ((ire->ire_src_addr == INADDR_ANY) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2481
		    (ire->ire_type & IRE_BROADCAST)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2482
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2483
			 * ire->ire_mp is non null when ire_mp passed in is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2484
			 * ire->ire_mp is set in ip_bind_insert_ire[_v6]().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2485
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2486
			if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2487
				ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2488
			if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2489
				ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2490
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2491
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2493
		if (tcp->tcp_ipha->ipha_src == INADDR_ANY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2494
			ipaddr_t src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2496
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2497
			 * ip_bind_connected() has stored the correct source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2498
			 * address in conn_src.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2499
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2500
			src_addr = tcp->tcp_connp->conn_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2501
			tcp->tcp_ipha->ipha_src = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2502
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2503
			 * Copy of the src addr. in tcp_t is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2504
			 * for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2505
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2506
			IN6_IPADDR_TO_V4MAPPED(src_addr, &tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2507
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2508
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2509
		 * Set the fragment bit so that IP will tell us if the MTU
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2510
		 * should change. IP tells us the latest setting of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2511
		 * ip_path_mtu_discovery through ire_frag_flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2512
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2513
		if (ip_path_mtu_discovery) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2514
			tcp->tcp_ipha->ipha_fragment_offset_and_flags =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2515
			    htons(IPH_DF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2516
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2517
		tcp->tcp_localnet = (ire->ire_gateway_addr == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2518
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2519
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2520
		 * For incoming connection ire_mp = NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2521
		 * For outgoing connection ire_mp != NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2522
		 * Technically we should check conn_incoming_ill
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2523
		 * when ire_mp is NULL and conn_outgoing_ill when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2524
		 * ire_mp is non-NULL. But this is performance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2525
		 * critical path and for IPV*_BOUND_IF, outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2526
		 * and incoming ill are always set to the same value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2527
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2528
		ill_t	*dst_ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2529
		ipif_t  *dst_ipif = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2530
		int match_flags = MATCH_IRE_RECURSIVE | MATCH_IRE_DEFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2531
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2532
		ASSERT(connp->conn_outgoing_ill == connp->conn_incoming_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2534
		if (connp->conn_outgoing_ill != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2535
			/* Outgoing or incoming path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2536
			int   err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2538
			dst_ill = conn_get_held_ill(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2539
			    &connp->conn_outgoing_ill, &err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2540
			if (err == ILL_LOOKUP_FAILED || dst_ill == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2541
				ip1dbg(("tcp_adapt_ire: ill_lookup failed\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2542
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2543
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2544
			match_flags |= MATCH_IRE_ILL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2545
			dst_ipif = dst_ill->ill_ipif;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2546
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2547
		ire = ire_ctable_lookup_v6(&tcp->tcp_connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2548
		    0, 0, dst_ipif, zoneid, match_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2550
		if (ire != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2551
			ire_cacheable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2552
			ire_uinfo = (ire_mp != NULL) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2553
			    &((ire_t *)ire_mp->b_rptr)->ire_uinfo:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2554
			    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2555
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2556
			if (ire_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2557
				ire = ire_ftable_lookup_v6(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2558
				    &tcp->tcp_connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2559
				    0, 0, 0, dst_ipif, &sire, zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2560
				    0, match_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2561
				if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2562
					if (dst_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2563
						ill_refrele(dst_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2564
					return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2565
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2566
				ire_uinfo = (sire != NULL) ? &sire->ire_uinfo :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2567
				    &ire->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2568
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2569
				ire = (ire_t *)ire_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2570
				ire_uinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2571
				    &((ire_t *)ire_mp->b_rptr)->ire_uinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2572
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2573
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2574
		if (dst_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2575
			ill_refrele(dst_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2577
		ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2578
		ASSERT(ire_uinfo != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2580
		if (IN6_IS_ADDR_UNSPECIFIED(&ire->ire_src_addr_v6) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2581
		    IN6_IS_ADDR_MULTICAST(&ire->ire_addr_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2582
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2583
			 * ire->ire_mp is non null when ire_mp passed in is used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2584
			 * ire->ire_mp is set in ip_bind_insert_ire[_v6]().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2585
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2586
			if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2587
				ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2588
			if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2589
				ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2590
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2591
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2593
		if (IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2594
			in6_addr_t	src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2595
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2596
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2597
			 * ip_bind_connected_v6() has stored the correct source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2598
			 * address per IPv6 addr. selection policy in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2599
			 * conn_src_v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2600
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2601
			src_addr = tcp->tcp_connp->conn_srcv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2602
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2603
			tcp->tcp_ip6h->ip6_src = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2604
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2605
			 * Copy of the src addr. in tcp_t is needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2606
			 * for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2607
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2608
			tcp->tcp_ip_src_v6 = src_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2609
			ASSERT(IN6_ARE_ADDR_EQUAL(&tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2610
			    &connp->conn_srcv6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2611
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2612
		tcp->tcp_localnet =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2613
		    IN6_IS_ADDR_UNSPECIFIED(&ire->ire_gateway_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2614
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2615
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2616
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2617
	 * This allows applications to fail quickly when connections are made
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2618
	 * to dead hosts. Hosts can be labeled dead by adding a reject route
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2619
	 * with both the RTF_REJECT and RTF_PRIVATE flags set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2620
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2621
	if ((ire->ire_flags & RTF_REJECT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2622
	    (ire->ire_flags & RTF_PRIVATE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2623
		goto error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2625
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2626
	 * Make use of the cached rtt and rtt_sd values to calculate the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2627
	 * initial RTO.  Note that they are already initialized in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2628
	 * tcp_init_values().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2629
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2630
	if (ire_uinfo->iulp_rtt != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2631
		clock_t	rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2633
		tcp->tcp_rtt_sa = ire_uinfo->iulp_rtt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2634
		tcp->tcp_rtt_sd = ire_uinfo->iulp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2635
		rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2636
		    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2637
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2638
		if (rto > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2639
			tcp->tcp_rto = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2640
		} else if (rto < tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2641
			tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2642
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2643
			tcp->tcp_rto = rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2644
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2645
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2646
	if (ire_uinfo->iulp_ssthresh != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2647
		tcp->tcp_cwnd_ssthresh = ire_uinfo->iulp_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2648
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2649
		tcp->tcp_cwnd_ssthresh = TCP_MAX_LARGEWIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2650
	if (ire_uinfo->iulp_spipe > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2651
		tcp->tcp_xmit_hiwater = MIN(ire_uinfo->iulp_spipe,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2652
		    tcp_max_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2653
		if (tcp_snd_lowat_fraction != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2654
			tcp->tcp_xmit_lowater = tcp->tcp_xmit_hiwater /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2655
			    tcp_snd_lowat_fraction;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2656
		(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2657
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2658
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2659
	 * Note that up till now, acceptor always inherits receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2660
	 * window from the listener.  But if there is a metrics associated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2661
	 * with a host, we should use that instead of inheriting it from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2662
	 * listener.  Thus we need to pass this info back to the caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2663
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2664
	if (ire_uinfo->iulp_rpipe > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2665
		tcp->tcp_rwnd = MIN(ire_uinfo->iulp_rpipe, tcp_max_buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2666
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2667
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2668
		 * For passive open, set tcp_rwnd to 0 so that the caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2669
		 * knows that there is no rpipe metric for this connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2670
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2671
		if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2672
			tcp->tcp_rwnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2673
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2674
	if (ire_uinfo->iulp_rtomax > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2675
		tcp->tcp_second_timer_threshold = ire_uinfo->iulp_rtomax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2676
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2677
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2678
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2679
	 * Use the metric option settings, iulp_tstamp_ok and iulp_wscale_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2680
	 * only for active open.  What this means is that if the other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2681
	 * uses timestamp or window scale option, TCP will also use those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2682
	 * options.  That is for passive open.  If the application sets a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2683
	 * large window, window scale is enabled regardless of the value in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2684
	 * iulp_wscale_ok.  This is the behavior since 2.6.  So we keep it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2685
	 * The only case left in passive open processing is the check for SACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2686
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2687
	 * For ECN, it should probably be like SACK.  But the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2688
	 * value is binary, so we treat it like the other cases.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2689
	 * metric only controls active open.  For passive open, the ndd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2690
	 * param, tcp_ecn_permitted, controls the behavior.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2691
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2692
	if (!tcp_detached) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2693
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2694
		 * The if check means that the following can only be turned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2695
		 * on by the metrics only IRE, but not off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2696
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2697
		if (ire_uinfo->iulp_tstamp_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2698
			tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2699
		if (ire_uinfo->iulp_wscale_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2700
			tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2701
		if (ire_uinfo->iulp_sack == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2702
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2703
		if (ire_uinfo->iulp_ecn_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2704
			tcp->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2705
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2706
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2707
		 * Passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2708
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2709
		 * As above, the if check means that SACK can only be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2710
		 * turned on by the metric only IRE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2711
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2712
		if (ire_uinfo->iulp_sack > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2713
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2714
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2715
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2717
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2718
	 * XXX: Note that currently, ire_max_frag can be as small as 68
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2719
	 * because of PMTUd.  So tcp_mss may go to negative if combined
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2720
	 * length of all those options exceeds 28 bytes.  But because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2721
	 * of the tcp_mss_min check below, we may not have a problem if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2722
	 * tcp_mss_min is of a reasonable value.  The default is 1 so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2723
	 * the negative problem still exists.  And the check defeats PMTUd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2724
	 * In fact, if PMTUd finds that the MSS should be smaller than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2725
	 * tcp_mss_min, TCP should turn off PMUTd and use the tcp_mss_min
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2726
	 * value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2727
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2728
	 * We do not deal with that now.  All those problems related to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2729
	 * PMTUd will be fixed later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2730
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2731
	ASSERT(ire->ire_max_frag != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2732
	mss = tcp->tcp_if_mtu = ire->ire_max_frag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2733
	if (tcp->tcp_ipp_fields & IPPF_USE_MIN_MTU) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2734
		if (tcp->tcp_ipp_use_min_mtu == IPV6_USE_MIN_MTU_NEVER) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2735
			mss = MIN(mss, IPV6_MIN_MTU);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2736
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2737
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2739
	/* Sanity check for MSS value. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2740
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2741
		mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2742
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2743
		mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2745
	if (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2746
	    (ire->ire_frag_flag & IPH_FRAG_HDR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2747
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2748
		 * After receiving an ICMPv6 "packet too big" message with a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2749
		 * MTU < 1280, and for multirouted IPv6 packets, the IP layer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2750
		 * will insert a 8-byte fragment header in every packet; we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2751
		 * reduce the MSS by that amount here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2752
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2753
		mss -= sizeof (ip6_frag_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2754
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2756
	if (tcp->tcp_ipsec_overhead == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2757
		tcp->tcp_ipsec_overhead = conn_ipsec_length(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2758
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2759
	mss -= tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2760
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2761
	if (mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2762
		mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2763
	if (mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2764
		mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2766
	/* Note that this is the maximum MSS, excluding all options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2767
	tcp->tcp_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2769
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2770
	 * Initialize the ISS here now that we have the full connection ID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2771
	 * The RFC 1948 method of initial sequence number generation requires
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2772
	 * knowledge of the full connection ID before setting the ISS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2773
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2775
	tcp_iss_init(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2777
	if (ire->ire_type & (IRE_LOOPBACK | IRE_LOCAL))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2778
		tcp->tcp_loopback = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2780
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2781
		hsp = tcp_hsp_lookup(tcp->tcp_remote);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2782
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2783
		hsp = tcp_hsp_lookup_ipv6(&tcp->tcp_remote_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2784
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2786
	if (hsp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2787
		/* Only modify if we're going to make them bigger */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2788
		if (hsp->tcp_hsp_sendspace > tcp->tcp_xmit_hiwater) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2789
			tcp->tcp_xmit_hiwater = hsp->tcp_hsp_sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2790
			if (tcp_snd_lowat_fraction != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2791
				tcp->tcp_xmit_lowater = tcp->tcp_xmit_hiwater /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2792
					tcp_snd_lowat_fraction;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2793
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2795
		if (hsp->tcp_hsp_recvspace > tcp->tcp_rwnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2796
			tcp->tcp_rwnd = hsp->tcp_hsp_recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2797
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2799
		/* Copy timestamp flag only for active open */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2800
		if (!tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2801
			tcp->tcp_snd_ts_ok = hsp->tcp_hsp_tstamp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2802
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2804
	if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2805
		IRE_REFRELE(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2807
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2808
	 * If we got an IRE_CACHE and an ILL, go through their properties;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2809
	 * otherwise, this is deferred until later when we have an IRE_CACHE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2810
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2811
	if (tcp->tcp_loopback ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2812
	    (ire_cacheable && (ill = ire_to_ill(ire)) != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2813
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2814
		 * For incoming, see if this tcp may be MDT-capable.  For
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2815
		 * outgoing, this process has been taken care of through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2816
		 * tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2817
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2818
		tcp_ire_ill_check(tcp, ire, ill, incoming);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2819
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2820
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2821
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2822
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2823
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2824
	 * Make sure that conn is not marked incipient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2825
	 * for incoming connections. A blind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2826
	 * removal of incipient flag is cheaper than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2827
	 * check and removal.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2828
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2829
	connp->conn_state_flags &= ~CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2831
	/* Must not cache forwarding table routes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2832
	if (ire_cacheable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2833
		rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2834
		if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2835
			connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2836
			IRE_UNTRACE_REF(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2837
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2838
			mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2839
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2840
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2841
		rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2842
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2843
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2845
	if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2846
		ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2847
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2849
error:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2850
	if (ire->ire_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2851
		ire_refrele(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2852
	if (sire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2853
		ire_refrele(sire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2854
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2855
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2857
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2858
 * tcp_bind is called (holding the writer lock) by tcp_wput_proto to process a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2859
 * O_T_BIND_REQ/T_BIND_REQ message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2860
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2861
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2862
tcp_bind(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2863
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2864
	sin_t	*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2865
	sin6_t	*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2866
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2867
	in_port_t requested_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2868
	in_port_t allocated_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2869
	struct T_bind_req *tbr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2870
	boolean_t	bind_to_req_port_only;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2871
	boolean_t	backlog_update = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2872
	boolean_t	user_specified;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2873
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2874
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2875
	uint_t	origipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2876
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2877
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2879
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2880
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2881
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2882
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2883
			    "tcp_bind: bad req, len %u",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2884
			    (uint_t)(mp->b_wptr - mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2885
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2886
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2887
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2888
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2889
	/* Make sure the largest address fits */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2890
	mp1 = reallocb(mp, sizeof (struct T_bind_ack) + sizeof (sin6_t) + 1, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2891
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2892
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2893
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2894
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2895
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2896
	tbr = (struct T_bind_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2897
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2898
		if ((tcp->tcp_state == TCPS_BOUND ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2899
		    tcp->tcp_state == TCPS_LISTEN) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2900
		    tcp->tcp_conn_req_max != tbr->CONIND_number &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2901
		    tbr->CONIND_number > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2902
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2903
			 * Handle listen() increasing CONIND_number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2904
			 * This is more "liberal" then what the TPI spec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2905
			 * requires but is needed to avoid a t_unbind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2906
			 * when handling listen() since the port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2907
			 * might be "stolen" between the unbind and bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2908
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2909
			backlog_update = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2910
			goto do_bind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2911
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2912
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2913
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2914
			    "tcp_bind: bad state, %d", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2915
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2916
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2917
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2918
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2919
	origipversion = tcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2921
	switch (tbr->ADDR_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2922
	case 0:			/* request for a generic port */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2923
		tbr->ADDR_offset = sizeof (struct T_bind_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2924
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2925
			tbr->ADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2926
			sin = (sin_t *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2927
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2928
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2929
			mp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2930
			tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2931
			IN6_IPADDR_TO_V4MAPPED(INADDR_ANY, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2932
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2933
			ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2934
			tbr->ADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2935
			sin6 = (sin6_t *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2936
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2937
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2938
			mp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2939
			tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2940
			V6_SET_ZERO(v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2941
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2942
		requested_port = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2943
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2945
	case sizeof (sin_t):	/* Complete IPv4 address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2946
		sin = (sin_t *)mi_offset_param(mp, tbr->ADDR_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2947
		    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2948
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2949
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2950
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2951
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2952
				    "tcp_bind: bad address parameter, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2953
				    "offset %d, len %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2954
				    tbr->ADDR_offset, tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2955
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2956
			tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2957
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2958
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2959
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2960
		 * With sockets sockfs will accept bogus sin_family in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2961
		 * bind() and replace it with the family used in the socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2962
		 * call.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2963
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2964
		if (sin->sin_family != AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2965
		    tcp->tcp_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2966
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2967
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2968
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2969
		requested_port = ntohs(sin->sin_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2970
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2971
		v4addr = sin->sin_addr.s_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2972
		IN6_IPADDR_TO_V4MAPPED(v4addr, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2973
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2975
	case sizeof (sin6_t): /* Complete IPv6 address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2976
		sin6 = (sin6_t *)mi_offset_param(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2977
		    tbr->ADDR_offset, sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2978
		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2979
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  2980
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2981
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2982
				    "tcp_bind: bad IPv6 address parameter, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2983
				    "offset %d, len %d", tbr->ADDR_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2984
				    tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2985
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2986
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2987
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2988
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2989
		if (sin6->sin6_family != AF_INET6 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2990
		    tcp->tcp_family != AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2991
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2992
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2993
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2994
		requested_port = ntohs(sin6->sin6_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2995
		tcp->tcp_ipversion = IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2996
		    IPV4_VERSION : IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2997
		v6addr = sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2998
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  2999
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3000
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3001
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3002
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3003
			    "tcp_bind: bad address length, %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3004
			    tbr->ADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3005
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3006
		tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3007
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3008
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3009
	tcp->tcp_bound_source_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3011
	/* Check for change in ipversion */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3012
	if (origipversion != tcp->tcp_ipversion) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3013
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3014
		err = tcp->tcp_ipversion == IPV6_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3015
		    tcp_header_init_ipv6(tcp) : tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3016
		if (err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3017
			tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3018
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3020
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3022
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3023
	 * Initialize family specific fields. Copy of the src addr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3024
	 * in tcp_t is needed for the lookup funcs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3025
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3026
	if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3027
		tcp->tcp_ip6h->ip6_src = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3028
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3029
		IN6_V4MAPPED_TO_IPADDR(&v6addr, tcp->tcp_ipha->ipha_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3030
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3031
	tcp->tcp_ip_src_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3033
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3034
	 * For O_T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3035
	 * Verify that the target port/addr is available, or choose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3036
	 * another.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3037
	 * For  T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3038
	 * Verify that the target port/addr is available or fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3039
	 * In both cases when it succeeds the tcp is inserted in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3040
	 * bind hash table. This ensures that the operation is atomic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3041
	 * under the lock on the hash bucket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3042
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3043
	bind_to_req_port_only = requested_port != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3044
	    tbr->PRIM_type != O_T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3045
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3046
	 * Get a valid port (within the anonymous range and should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3047
	 * be a privileged one) to use if the user has not given a port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3048
	 * If multiple threads are here, they may all start with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3049
	 * with the same initial port. But, it should be fine as long as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3050
	 * tcp_bindi will ensure that no two threads will be assigned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3051
	 * the same port.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3052
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3053
	 * NOTE: XXX If a privileged process asks for an anonymous port, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3054
	 * still check for ports only in the range > tcp_smallest_non_priv_port,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3055
	 * unless TCP_ANONPRIVBIND option is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3056
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3057
	if (requested_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3058
		requested_port = tcp->tcp_anon_priv_bind ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3059
		    tcp_get_next_priv_port() :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3060
		    tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3061
		user_specified = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3062
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3063
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3064
		boolean_t priv = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3065
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3066
		 * If the requested_port is in the well-known privileged range,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3067
		 * verify that the stream was opened by a privileged user.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3068
		 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3069
		 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3070
		 * - the fact that the address of the array and its size never
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3071
		 *   changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3072
		 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3073
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3074
		if (requested_port < tcp_smallest_nonpriv_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3075
			priv = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3076
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3077
			for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3078
				if (requested_port ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3079
				    tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3080
					priv = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3081
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3082
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3083
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3084
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3085
		if (priv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3086
			cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3088
			if (secpolicy_net_privaddr(cr, requested_port) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3089
				if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3090
					(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3091
					    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3092
					    "tcp_bind: no priv for port %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3093
					    requested_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3094
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3095
				tcp_err_ack(tcp, mp, TACCES, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3096
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3097
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3098
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3099
		user_specified = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3100
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3102
	allocated_port = tcp_bindi(tcp, requested_port, &v6addr,
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3103
	    tcp->tcp_reuseaddr, B_FALSE, bind_to_req_port_only, user_specified);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3105
	if (allocated_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3106
		if (bind_to_req_port_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3107
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3108
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3109
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3110
				    "tcp_bind: requested addr busy");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3111
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3112
			tcp_err_ack(tcp, mp, TADDRBUSY, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3113
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3114
			/* If we are out of ports, fail the bind. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3115
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3116
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3117
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3118
				    "tcp_bind: out of ports?");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3119
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3120
			tcp_err_ack(tcp, mp, TNOADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3121
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3122
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3124
	ASSERT(tcp->tcp_state == TCPS_BOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3125
do_bind:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3126
	if (!backlog_update) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3127
		if (tcp->tcp_family == AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3128
			sin->sin_port = htons(allocated_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3129
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3130
			sin6->sin6_port = htons(allocated_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3131
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3132
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3133
		if (tbr->CONIND_number != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3134
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3135
			    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3136
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3137
			/* Just verify the local IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3138
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3139
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3140
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3141
		if (tbr->CONIND_number != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3142
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3143
			    sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3144
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3145
			/* Just verify the local IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3146
			mp1 = tcp_ip_bind_mp(tcp, tbr->PRIM_type,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3147
			    IPV6_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3148
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3149
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3150
	if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3151
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3152
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3153
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3155
	tbr->PRIM_type = T_BIND_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3156
	mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3158
	/* Chain in the reply mp for tcp_rput() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3159
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3160
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3162
	tcp->tcp_conn_req_max = tbr->CONIND_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3163
	if (tcp->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3164
		if (tcp->tcp_conn_req_max < tcp_conn_req_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3165
			tcp->tcp_conn_req_max = tcp_conn_req_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3166
		if (tcp->tcp_conn_req_max > tcp_conn_req_max_q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3167
			tcp->tcp_conn_req_max = tcp_conn_req_max_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3168
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3169
		 * If this is a listener, do not reset the eager list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3170
		 * and other stuffs.  Note that we don't check if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3171
		 * existing eager list meets the new tcp_conn_req_max
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3172
		 * requirement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3173
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3174
		if (tcp->tcp_state != TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3175
			tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3176
			/* Initialize the chain. Don't need the eager_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3177
			tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3178
			tcp->tcp_second_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3179
			    tcp_ip_abort_linterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3180
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3183
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3184
	 * We can call ip_bind directly which returns a T_BIND_ACK mp. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3185
	 * processing continues in tcp_rput_other().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3186
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3187
	if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3188
		ASSERT(tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3189
		mp = ip_bind_v6(q, mp, tcp->tcp_connp, &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3190
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3191
		ASSERT(!tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3192
		mp = ip_bind_v4(q, mp, tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3193
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3194
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3195
	 * If the bind cannot complete immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3196
	 * IP will arrange to call tcp_rput_other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3197
	 * when the bind completes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3198
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3199
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3200
		tcp_rput_other(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3201
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3202
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3203
		 * Bind will be resumed later. Need to ensure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3204
		 * that conn doesn't disappear when that happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3205
		 * This will be decremented in ip_resume_tcp_bind().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3206
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3207
		CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3208
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3209
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3210
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3212
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3213
 * If the "bind_to_req_port_only" parameter is set, if the requested port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3214
 * number is available, return it, If not return 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3215
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3216
 * If "bind_to_req_port_only" parameter is not set and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3217
 * If the requested port number is available, return it.  If not, return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3218
 * the first anonymous port we happen across.  If no anonymous ports are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3219
 * available, return 0. addr is the requested local address, if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3220
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3221
 * In either case, when succeeding update the tcp_t to record the port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3222
 * and insert it in the bind hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3223
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3224
 * Note that TCP over IPv4 and IPv6 sockets can use the same port number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3225
 * without setting SO_REUSEADDR. This is needed so that they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3226
 * can be viewed as two independent transport protocols.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3227
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3228
static in_port_t
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3229
tcp_bindi(tcp_t *tcp, in_port_t port, const in6_addr_t *laddr,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3230
    int reuseaddr, boolean_t quick_connect,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3231
    boolean_t bind_to_req_port_only, boolean_t user_specified)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3232
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3233
	/* number of times we have run around the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3234
	int count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3235
	/* maximum number of times to run around the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3236
	int loopmax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3237
	zoneid_t zoneid = tcp->tcp_connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3239
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3240
	 * Lookup for free addresses is done in a loop and "loopmax"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3241
	 * influences how long we spin in the loop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3242
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3243
	if (bind_to_req_port_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3244
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3245
		 * If the requested port is busy, don't bother to look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3246
		 * for a new one. Setting loop maximum count to 1 has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3247
		 * that effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3248
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3249
		loopmax = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3250
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3251
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3252
		 * If the requested port is busy, look for a free one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3253
		 * in the anonymous port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3254
		 * Set loopmax appropriately so that one does not look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3255
		 * forever in the case all of the anonymous ports are in use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3256
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3257
		if (tcp->tcp_anon_priv_bind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3258
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3259
			 * loopmax =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3260
			 * 	(IPPORT_RESERVED-1) - tcp_min_anonpriv_port + 1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3261
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3262
			loopmax = IPPORT_RESERVED - tcp_min_anonpriv_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3263
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3264
			loopmax = (tcp_largest_anon_port -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3265
			    tcp_smallest_anon_port + 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3266
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3267
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3268
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3269
		uint16_t	lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3270
		tf_t		*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3271
		tcp_t		*ltcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3273
		lport = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3274
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3275
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3276
		 * Ensure that the tcp_t is not currently in the bind hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3277
		 * Hold the lock on the hash bucket to ensure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3278
		 * the duplicate check plus the insertion is an atomic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3279
		 * operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3280
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3281
		 * This function does an inline lookup on the bind hash list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3282
		 * Make sure that we access only members of tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3283
		 * and that we don't look at tcp_tcp, since we are not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3284
		 * doing a CONN_INC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3285
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3286
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3287
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(lport)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3288
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3289
		for (ltcp = tbf->tf_tcp; ltcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3290
		    ltcp = ltcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3291
			if (lport != ltcp->tcp_lport ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3292
			    ltcp->tcp_connp->conn_zoneid != zoneid) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3293
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3294
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3296
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3297
			 * If TCP_EXCLBIND is set for either the bound or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3298
			 * binding endpoint, the semantics of bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3299
			 * is changed according to the following.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3300
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3301
			 * spec = specified address (v4 or v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3302
			 * unspec = unspecified address (v4 or v6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3303
			 * A = specified addresses are different for endpoints
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3304
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3305
			 * bound	bind to		allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3306
			 * -------------------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3307
			 * unspec	unspec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3308
			 * unspec	spec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3309
			 * spec		unspec		no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3310
			 * spec		spec		yes if A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3311
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3312
			 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3313
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3314
			 * 1. Because of TLI semantics, an endpoint can go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3315
			 * back from, say TCP_ESTABLISHED to TCPS_LISTEN or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3316
			 * TCPS_BOUND, depending on whether it is originally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3317
			 * a listener or not.  That is why we need to check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3318
			 * for states greater than or equal to TCPS_BOUND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3319
			 * here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3320
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3321
			 * 2. Ideally, we should only check for state equals
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3322
			 * to TCPS_LISTEN. And the following check should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3323
			 * added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3324
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3325
			 * if (ltcp->tcp_state == TCPS_LISTEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3326
			 *	!reuseaddr || !ltcp->tcp_reuseaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3327
			 *		...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3328
			 * }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3329
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3330
			 * The semantics will be changed to this.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3331
			 * endpoint on the list is in state not equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3332
			 * TCPS_LISTEN and both endpoints have SO_REUSEADDR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3333
			 * set, let the bind succeed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3334
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3335
			 * But because of (1), we cannot do that now.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3336
			 * in future, we can change this going back semantics,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3337
			 * we can add the above check.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3338
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3339
			if (ltcp->tcp_exclbind || tcp->tcp_exclbind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3340
				if (V6_OR_V4_INADDR_ANY(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3341
				    ltcp->tcp_bound_source_v6) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3342
				    V6_OR_V4_INADDR_ANY(*laddr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3343
				    IN6_ARE_ADDR_EQUAL(laddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3344
				    &ltcp->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3345
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3346
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3347
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3348
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3350
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3351
			 * Check ipversion to allow IPv4 and IPv6 sockets to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3352
			 * have disjoint port number spaces, if *_EXCLBIND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3353
			 * is not set and only if the application binds to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3354
			 * specific port. We use the same autoassigned port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3355
			 * number space for IPv4 and IPv6 sockets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3356
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3357
			if (tcp->tcp_ipversion != ltcp->tcp_ipversion &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3358
			    bind_to_req_port_only)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3359
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3360
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3361
			/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3362
			 * Ideally, we should make sure that the source
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3363
			 * address, remote address, and remote port in the
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3364
			 * four tuple for this tcp-connection is unique.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3365
			 * However, trying to find out the local source
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3366
			 * address would require too much code duplication
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3367
			 * with IP, since IP needs needs to have that code
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3368
			 * to support userland TCP implementations.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3369
			 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3370
			if (quick_connect &&
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3371
			    (ltcp->tcp_state > TCPS_LISTEN) &&
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3372
			    ((tcp->tcp_fport != ltcp->tcp_fport) ||
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3373
				!IN6_ARE_ADDR_EQUAL(&tcp->tcp_remote_v6,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3374
				    &ltcp->tcp_remote_v6)))
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3375
				continue;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3376
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3377
			if (!reuseaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3378
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3379
				 * No socket option SO_REUSEADDR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3380
				 * If existing port is bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3381
				 * a non-wildcard IP address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3382
				 * and the requesting stream is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3383
				 * bound to a distinct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3384
				 * different IP addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3385
				 * (non-wildcard, also), keep
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3386
				 * going.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3387
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3388
				if (!V6_OR_V4_INADDR_ANY(*laddr) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3389
				    !V6_OR_V4_INADDR_ANY(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3390
				    ltcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3391
				    !IN6_ARE_ADDR_EQUAL(laddr,
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3392
					&ltcp->tcp_bound_source_v6))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3393
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3394
				if (ltcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3395
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3396
					 * This port is being used and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3397
					 * its state is >= TCPS_BOUND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3398
					 * so we can't bind to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3399
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3400
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3401
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3402
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3403
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3404
				 * socket option SO_REUSEADDR is set on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3405
				 * binding tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3406
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3407
				 * If two streams are bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3408
				 * same IP address or both addr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3409
				 * and bound source are wildcards
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3410
				 * (INADDR_ANY), we want to stop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3411
				 * searching.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3412
				 * We have found a match of IP source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3413
				 * address and source port, which is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3414
				 * refused regardless of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3415
				 * SO_REUSEADDR setting, so we break.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3416
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3417
				if (IN6_ARE_ADDR_EQUAL(laddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3418
				    &ltcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3419
				    (ltcp->tcp_state == TCPS_LISTEN ||
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  3420
					ltcp->tcp_state == TCPS_BOUND))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3421
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3422
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3423
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3424
		if (ltcp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3425
			/* The port number is busy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3426
			mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3427
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3428
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3429
			 * This port is ours. Insert in fanout and mark as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3430
			 * bound to prevent others from getting the port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3431
			 * number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3432
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3433
			tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3434
			tcp->tcp_lport = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3435
			*(uint16_t *)tcp->tcp_tcph->th_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3437
			ASSERT(&tcp_bind_fanout[TCP_BIND_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3438
			    tcp->tcp_lport)] == tbf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3439
			tcp_bind_hash_insert(tbf, tcp, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3441
			mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3442
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3443
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3444
			 * We don't want tcp_next_port_to_try to "inherit"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3445
			 * a port number supplied by the user in a bind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3446
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3447
			if (user_specified)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3448
				return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3450
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3451
			 * This is the only place where tcp_next_port_to_try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3452
			 * is updated. After the update, it may or may not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3453
			 * be in the valid range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3454
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3455
			if (!tcp->tcp_anon_priv_bind)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3456
				tcp_next_port_to_try = port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3457
			return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3458
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3460
		if (tcp->tcp_anon_priv_bind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3461
			port = tcp_get_next_priv_port();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3462
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3463
			if (count == 0 && user_specified) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3464
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3465
				 * We may have to return an anonymous port. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3466
				 * get one to start with.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3467
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3468
				port =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3469
				    tcp_update_next_port(tcp_next_port_to_try,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3470
					B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3471
				user_specified = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3472
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3473
				port = tcp_update_next_port(port + 1, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3474
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3475
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3477
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3478
		 * Don't let this loop run forever in the case where
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3479
		 * all of the anonymous ports are in use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3480
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3481
	} while (++count < loopmax);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3482
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3483
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3485
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3486
 * We are dying for some reason.  Try to do it gracefully.  (May be called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3487
 * as writer.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3488
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3489
 * Return -1 if the structure was not cleaned up (if the cleanup had to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3490
 * done by a service procedure).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3491
 * TBD - Should the return value distinguish between the tcp_t being
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3492
 * freed and it being reinitialized?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3493
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3494
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3495
tcp_clean_death(tcp_t *tcp, int err, uint8_t tag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3496
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3497
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3498
	queue_t	*q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3500
	TCP_CLD_STAT(tag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3502
#if TCP_TAG_CLEAN_DEATH
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3503
	tcp->tcp_cleandeathtag = tag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3504
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3506
	if (tcp->tcp_linger_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3507
	    TCP_TIMER_CANCEL(tcp, tcp->tcp_linger_tid) >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3508
		tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3509
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3510
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3511
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3512
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3513
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3514
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3515
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3516
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3518
	if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3519
		if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3520
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3521
			 * Its an eager that we are dealing with. We close the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3522
			 * eager but in case a conn_ind has already gone to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3523
			 * listener, let tcp_accept_finish() send a discon_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3524
			 * to the listener and drop the last reference. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3525
			 * listener doesn't even know about the eager i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3526
			 * conn_ind hasn't gone up, blow away the eager and drop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3527
			 * the last reference as well. If the conn_ind has gone
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3528
			 * up, state should be BOUND. tcp_accept_finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3529
			 * will figure out that the connection has received a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3530
			 * RST and will send a DISCON_IND to the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3531
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3532
			tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3533
			if (tcp->tcp_conn.tcp_eager_conn_ind != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3534
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3535
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3536
				tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3537
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3538
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3539
			tcp_close_detached(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3540
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3541
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3542
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3544
	TCP_STAT(tcp_clean_death_nondetached);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3545
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3546
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3547
	 * If T_ORDREL_IND has not been sent yet (done when service routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3548
	 * is run) postpone cleaning up the endpoint until service routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3549
	 * has sent up the T_ORDREL_IND. Avoid clearing out an existing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3550
	 * client_errno since tcp_close uses the client_errno field.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3551
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3552
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3553
		if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3554
			tcp->tcp_client_errno = err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3556
		tcp->tcp_deferred_clean_death = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3557
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3558
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3560
	q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3561
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3562
	/* Trash all inbound data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3563
	flushq(q, FLUSHALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3565
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3566
	 * If we are at least part way open and there is error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3567
	 * (err==0 implies no error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3568
	 * notify our client by a T_DISCON_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3569
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3570
	if ((tcp->tcp_state >= TCPS_SYN_SENT) && err) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3571
		if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3572
		    !TCP_IS_SOCKET(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3573
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3574
			 * Send M_FLUSH according to TPI. Because sockets will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3575
			 * (and must) ignore FLUSHR we do that only for TPI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3576
			 * endpoints and sockets in STREAMS mode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3577
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3578
			(void) putnextctl1(q, M_FLUSH, FLUSHR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3579
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3580
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3581
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3582
			    "tcp_clean_death: discon err %d", err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3583
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3584
		mp = mi_tpi_discon_ind(NULL, err, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3585
		if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3586
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3587
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3588
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  3589
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3590
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3591
				    "tcp_clean_death, sending M_ERROR");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3592
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3593
			(void) putnextctl1(q, M_ERROR, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3594
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3595
		if (tcp->tcp_state <= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3596
			/* SYN_SENT or SYN_RCVD */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3597
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3598
		} else if (tcp->tcp_state <= TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3599
			/* ESTABLISHED or CLOSE_WAIT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3600
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3601
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3602
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3603
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3604
	tcp_reinit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3605
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3606
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3608
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3609
 * In case tcp is in the "lingering state" and waits for the SO_LINGER timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3610
 * to expire, stop the wait and finish the close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3611
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3612
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3613
tcp_stop_lingering(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3614
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3615
	clock_t	delta = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3617
	tcp->tcp_linger_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3618
	if (tcp->tcp_state > TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3619
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3620
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3621
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3622
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3624
		if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3625
			delta = TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3626
			tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3627
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3628
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3629
		 * Need to cancel those timers which will not be used when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3630
		 * TCP is detached.  This has to be done before the tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3631
		 * is set to the global queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3632
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3633
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3634
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3636
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3637
		tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3638
		tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3639
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3640
		if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3641
			tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3642
			TCP_DBGSTAT(tcp_detach_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3643
			goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3644
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3645
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3646
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3647
		 * If delta is zero the timer event wasn't executed and was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3648
		 * successfully canceled. In this case we need to restart it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3649
		 * with the minimal delta possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3650
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3651
		if (delta >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3652
			tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3653
			    delta ? delta : 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3654
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3655
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3656
		tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3657
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3658
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3659
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3660
	/* Signal closing thread that it can complete close */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3661
	mutex_enter(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3662
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3663
	tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3664
	tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3665
	tcp->tcp_closed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3666
	cv_signal(&tcp->tcp_closecv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3667
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3668
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3669
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3670
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3671
 * Handle lingering timeouts. This function is called when the SO_LINGER timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3672
 * expires.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3673
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3674
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3675
tcp_close_linger_timeout(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3676
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3677
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3678
	tcp_t 	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3680
	tcp->tcp_client_errno = ETIMEDOUT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3681
	tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3682
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3684
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3685
tcp_close(queue_t *q, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3686
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3687
	conn_t		*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3688
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3689
	mblk_t 		*mp = &tcp->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3690
	boolean_t	conn_ioctl_cleanup_reqd = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3691
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3692
	ASSERT(WR(q)->q_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3693
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3694
	ASSERT((connp->conn_flags & IPCL_TCPMOD) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3696
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3697
	 * We are being closed as /dev/tcp or /dev/tcp6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3698
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3699
	 * Mark the conn as closing. ill_pending_mp_add will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3700
	 * add any mp to the pending mp list, after this conn has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3701
	 * started closing. Same for sq_pending_mp_add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3702
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3703
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3704
	connp->conn_state_flags |= CONN_CLOSING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3705
	if (connp->conn_oper_pending_ill != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3706
		conn_ioctl_cleanup_reqd = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3707
	CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3708
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3709
	tcp->tcp_closeflags = (uint8_t)flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3710
	ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3712
	(*tcp_squeue_close_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3713
	    tcp_close_output, connp, SQTAG_IP_TCP_CLOSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3715
	mutex_enter(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3716
	while (!tcp->tcp_closed)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3717
		cv_wait(&tcp->tcp_closecv, &tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3718
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3719
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3720
	 * In the case of listener streams that have eagers in the q or q0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3721
	 * we wait for the eagers to drop their reference to us. tcp_rq and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3722
	 * tcp_wq of the eagers point to our queues. By waiting for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3723
	 * refcnt to drop to 1, we are sure that the eagers have cleaned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3724
	 * up their queue pointers and also dropped their references to us.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3725
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3726
	if (tcp->tcp_wait_for_eagers) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3727
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3728
		while (connp->conn_ref != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3729
			cv_wait(&connp->conn_cv, &connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3730
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3731
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3732
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3733
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3734
	 * ioctl cleanup. The mp is queued in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3735
	 * ill_pending_mp or in the sq_pending_mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3736
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3737
	if (conn_ioctl_cleanup_reqd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3738
		conn_ioctl_cleanup(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3740
	qprocsoff(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3741
	inet_minor_free(ip_minor_arena, connp->conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3743
	ASSERT(connp->conn_cred != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3744
	crfree(connp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3745
	tcp->tcp_cred = connp->conn_cred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3746
	tcp->tcp_cpid = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3748
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3749
	 * Drop IP's reference on the conn. This is the last reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3750
	 * on the connp if the state was less than established. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3751
	 * connection has gone into timewait state, then we will have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3752
	 * one ref for the TCP and one more ref (total of two) for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3753
	 * classifier connected hash list (a timewait connections stays
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3754
	 * in connected hash till closed).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3755
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3756
	 * We can't assert the references because there might be other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3757
	 * transient reference places because of some walkers or queued
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3758
	 * packets in squeue for the timewait state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3759
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3760
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3761
	q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3762
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3763
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3765
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3766
tcpclose_accept(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3767
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3768
	ASSERT(WR(q)->q_qinfo == &tcp_acceptor_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3770
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3771
	 * We had opened an acceptor STREAM for sockfs which is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3772
	 * now being closed due to some error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3773
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3774
	qprocsoff(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3775
	inet_minor_free(ip_minor_arena, (dev_t)q->q_ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3776
	q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3777
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3778
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3780
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3781
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3782
 * Called by streams close routine via squeues when our client blows off her
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3783
 * descriptor, we take this to mean: "close the stream state NOW, close the tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3784
 * connection politely" When SO_LINGER is set (with a non-zero linger time and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3785
 * it is not a nonblocking socket) then this routine sleeps until the FIN is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3786
 * acked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3787
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3788
 * NOTE: tcp_close potentially returns error when lingering.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3789
 * However, the stream head currently does not pass these errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3790
 * to the application. 4.4BSD only returns EINTR and EWOULDBLOCK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3791
 * errors to the application (from tsleep()) and not errors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3792
 * like ECONNRESET caused by receiving a reset packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3793
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3795
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3796
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3797
tcp_close_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3798
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3799
	char	*msg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3800
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3801
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3802
	clock_t	delta = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3804
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3805
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3807
	/* Cancel any pending timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3808
	if (tcp->tcp_ordrelid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3809
		if (tcp->tcp_timeout) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3810
			(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ordrelid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3811
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3812
		tcp->tcp_ordrelid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3813
		tcp->tcp_timeout = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3816
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3817
	if (tcp->tcp_conn_req_cnt_q0 != 0 || tcp->tcp_conn_req_cnt_q != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3818
		/* Cleanup for listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3819
		tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3820
		tcp->tcp_wait_for_eagers = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3821
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3822
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3824
	connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3825
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3827
	msg = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3828
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3829
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3830
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3831
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3832
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3833
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3834
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3835
		msg = "tcp_close, during connect";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3836
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3837
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3838
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3839
		 * Close during the connect 3-way handshake
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3840
		 * but here there may or may not be pending data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3841
		 * already on queue. Process almost same as in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3842
		 * the ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3843
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3844
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3845
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3846
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3847
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3849
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3850
		 * If SO_LINGER has set a zero linger time, abort the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3851
		 * connection with a reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3852
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3853
		if (tcp->tcp_linger && tcp->tcp_lingertime == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3854
			msg = "tcp_close, zero lingertime";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3855
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3856
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3858
		ASSERT(tcp->tcp_hard_bound || tcp->tcp_hard_binding);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3859
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3860
		 * Abort connection if there is unread data queued.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3861
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3862
		if (tcp->tcp_rcv_list || tcp->tcp_reass_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3863
			msg = "tcp_close, unread data";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3864
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3865
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3866
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3867
		 * tcp_hard_bound is now cleared thus all packets go through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3868
		 * tcp_lookup. This fact is used by tcp_detach below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3869
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3870
		 * We have done a qwait() above which could have possibly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3871
		 * drained more messages in turn causing transition to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3872
		 * different state. Check whether we have to do the rest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3873
		 * of the processing or not.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3874
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3875
		if (tcp->tcp_state <= TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3876
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3878
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3879
		 * Transmit the FIN before detaching the tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3880
		 * After tcp_detach returns this queue/perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3881
		 * no longer owns the tcp_t thus others can modify it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3882
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3883
		(void) tcp_xmit_end(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3885
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3886
		 * If lingering on close then wait until the fin is acked,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3887
		 * the SO_LINGER time passes, or a reset is sent/received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3888
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3889
		if (tcp->tcp_linger && tcp->tcp_lingertime > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3890
		    !(tcp->tcp_fin_acked) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3891
		    tcp->tcp_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3892
			if (tcp->tcp_closeflags & (FNDELAY|FNONBLOCK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3893
				tcp->tcp_client_errno = EWOULDBLOCK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3894
			} else if (tcp->tcp_client_errno == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3895
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3896
				ASSERT(tcp->tcp_linger_tid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3898
				tcp->tcp_linger_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3899
				    tcp_close_linger_timeout,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3900
				    tcp->tcp_lingertime * hz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3902
				/* tcp_close_linger_timeout will finish close */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3903
				if (tcp->tcp_linger_tid == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3904
					tcp->tcp_client_errno = ENOSR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3905
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3906
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3907
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3909
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3910
			 * Check if we need to detach or just close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3911
			 * the instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3912
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3913
			if (tcp->tcp_state <= TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3914
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3915
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3916
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3917
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3918
		 * Make sure that no other thread will access the tcp_rq of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3919
		 * this instance (through lookups etc.) as tcp_rq will go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3920
		 * away shortly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3921
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3922
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3923
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3924
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3925
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3926
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3928
		if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3929
			delta = TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3930
			tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3931
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3932
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3933
		 * Need to cancel those timers which will not be used when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3934
		 * TCP is detached.  This has to be done before the tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3935
		 * is set to the global queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3936
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3937
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3939
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3940
		if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3941
			tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3942
			TCP_DBGSTAT(tcp_detach_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3943
			ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3944
			goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3945
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3947
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3948
		 * If delta is zero the timer event wasn't executed and was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3949
		 * successfully canceled. In this case we need to restart it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3950
		 * with the minimal delta possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3951
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3952
		if (delta >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3953
			tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3954
			    delta ? delta : 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3956
		ASSERT(connp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3957
		goto finish;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3958
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3960
	/* Detach did not complete. Still need to remove q from stream. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3961
	if (msg) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3962
		if (tcp->tcp_state == TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3963
		    tcp->tcp_state == TCPS_CLOSE_WAIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3964
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3965
		if (tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3966
		    tcp->tcp_state == TCPS_SYN_RCVD)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3967
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3968
		tcp_xmit_ctl(msg, tcp,  tcp->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3969
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3971
	tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3972
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3973
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3975
finish:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3976
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3977
	 * Although packets are always processed on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3978
	 * tcp's perimeter and access is serialized via squeue's,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3979
	 * IP still needs a queue when sending packets in time_wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3980
	 * state so use WR(tcp_g_q) till ip_output() can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3981
	 * changed to deal with just connp. For read side, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3982
	 * could have set tcp_rq to NULL but there are some cases
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3983
	 * in tcp_rput_data() from early days of this code which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3984
	 * do a putnext without checking if tcp is closed. Those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3985
	 * need to be identified before both tcp_rq and tcp_wq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3986
	 * can be set to NULL and tcp_q_q can disappear forever.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3987
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3988
	mutex_enter(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3989
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3990
	 * Don't change the queues in the case of a listener that has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3991
	 * eagers in its q or q0. It could surprise the eagers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3992
	 * Instead wait for the eagers outside the squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3993
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3994
	if (!tcp->tcp_wait_for_eagers) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3995
		tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3996
		tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3997
		tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3998
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  3999
	/* Signal tcp_close() to finish closing. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4000
	tcp->tcp_closed = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4001
	cv_signal(&tcp->tcp_closecv);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4002
	mutex_exit(&tcp->tcp_closelock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4003
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4004
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4006
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4007
 * Clean up the b_next and b_prev fields of every mblk pointed at by *mpp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4008
 * Some stream heads get upset if they see these later on as anything but NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4009
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4010
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4011
tcp_close_mpp(mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4012
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4013
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4014
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4015
	if ((mp = *mpp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4016
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4017
			mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4018
			mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4019
		} while ((mp = mp->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4021
		mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4022
		*mpp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4023
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4024
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4025
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4026
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4027
/* Do detached close. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4028
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4029
tcp_close_detached(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4030
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4031
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4032
		tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4033
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4034
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4035
	 * Clustering code serializes TCP disconnect callbacks and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4036
	 * cluster tcp list walks by blocking a TCP disconnect callback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4037
	 * if a cluster tcp list walk is in progress. This ensures
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4038
	 * accurate accounting of TCPs in the cluster code even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4039
	 * the TCP list walk itself is not atomic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4040
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4041
	tcp_closei_local(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4042
	CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4043
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4045
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4046
 * Stop all TCP timers, and free the timer mblks if requested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4047
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4048
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4049
tcp_timers_stop(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4050
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4051
	if (tcp->tcp_timer_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4052
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4053
		tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4054
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4055
	if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4056
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4057
		tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4058
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4059
	if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4060
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4061
		tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4062
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4063
	if (tcp->tcp_push_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4064
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_push_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4065
		tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4066
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4067
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4068
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4069
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4070
 * The tcp_t is going away. Remove it from all lists and set it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4071
 * to TCPS_CLOSED. The freeing up of memory is deferred until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4072
 * tcp_inactive. This is needed since a thread in tcp_rput might have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4073
 * done a CONN_INC_REF on this structure before it was removed from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4074
 * hashes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4075
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4076
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4077
tcp_closei_local(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4078
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4079
	ire_t 	*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4080
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4081
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4082
	if (!TCP_IS_SOCKET(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4083
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4085
	UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4086
	tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4087
	UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4088
	tcp->tcp_obsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4089
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4090
	 * If we are an eager connection hanging off a listener that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4091
	 * hasn't formally accepted the connection yet, get off his
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4092
	 * list and blow off any data that we have accumulated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4093
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4094
	if (tcp->tcp_listener != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4095
		tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4096
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4097
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4098
		 * tcp_eager_conn_ind == NULL means that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4099
		 * conn_ind has already gone to listener. At
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4100
		 * this point, eager will be closed but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4101
		 * leave it in listeners eager list so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4102
		 * if listener decides to close without doing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4103
		 * accept, we can clean this up. In tcp_wput_accept
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4104
		 * we take case of the case of accept on closed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4105
		 * eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4106
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4107
		if (tcp->tcp_conn.tcp_eager_conn_ind != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4108
			tcp_eager_unlink(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4109
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4110
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4111
			 * We don't want to have any pointers to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4112
			 * listener queue, after we have released our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4113
			 * reference on the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4114
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4115
			tcp->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4116
			tcp->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4117
			CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4118
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4119
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4120
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4121
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4123
	/* Stop all the timers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4124
	tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4125
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4126
	if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4127
		if (tcp->tcp_ip_addr_cache) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4128
			kmem_free((void *)tcp->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4129
			    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4130
			tcp->tcp_ip_addr_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4131
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4132
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4133
	if (tcp->tcp_flow_stopped)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4134
		tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4136
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4137
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4138
	 * If the tcp_time_wait_collector (which runs outside the squeue)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4139
	 * is trying to remove this tcp from the time wait list, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4140
	 * block in tcp_time_wait_remove while trying to acquire the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4141
	 * tcp_time_wait_lock. The logic in tcp_time_wait_collector also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4142
	 * requires the ipcl_hash_remove to be ordered after the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4143
	 * tcp_time_wait_remove for the refcnt checks to work correctly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4144
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4145
	if (tcp->tcp_state == TCPS_TIME_WAIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4146
		tcp_time_wait_remove(tcp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4147
	CL_INET_DISCONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4148
	ipcl_hash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4150
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4151
	 * Delete the cached ire in conn_ire_cache and also mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4152
	 * the conn as CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4153
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4154
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4155
	connp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4156
	ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4157
	connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4158
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4159
	if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4160
		IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4162
	/* Need to cleanup any pending ioctls */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4163
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4164
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4165
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4166
	tcp->tcp_state = TCPS_CLOSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4167
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4169
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4170
 * tcp is dying (called from ipcl_conn_destroy and error cases).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4171
 * Free the tcp_t in either case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4172
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4173
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4174
tcp_free(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4175
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4176
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4177
	ip6_pkt_t	*ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4179
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4180
	ASSERT(tcp->tcp_ptpahn == NULL && tcp->tcp_acceptor_hash == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4182
	tcp->tcp_rq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4183
	tcp->tcp_wq = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4185
	tcp_close_mpp(&tcp->tcp_xmit_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4186
	tcp_close_mpp(&tcp->tcp_reass_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4187
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4188
		/* Free b_next chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4189
		tcp_close_mpp(&tcp->tcp_rcv_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4190
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4191
	if ((mp = tcp->tcp_urp_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4192
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4193
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4194
	if ((mp = tcp->tcp_urp_mark_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4195
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4196
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4198
	if (tcp->tcp_fused_sigurg_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4199
		freeb(tcp->tcp_fused_sigurg_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4200
		tcp->tcp_fused_sigurg_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4201
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4203
	if (tcp->tcp_sack_info != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4204
		if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4205
			TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4206
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4207
		bzero(tcp->tcp_sack_info, sizeof (tcp_sack_info_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4208
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4210
	if (tcp->tcp_hopopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4211
		mi_free(tcp->tcp_hopopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4212
		tcp->tcp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4213
		tcp->tcp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4214
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4215
	ASSERT(tcp->tcp_hopoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4216
	if (tcp->tcp_dstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4217
		mi_free(tcp->tcp_dstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4218
		tcp->tcp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4219
		tcp->tcp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4220
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4221
	ASSERT(tcp->tcp_dstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4222
	if (tcp->tcp_rtdstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4223
		mi_free(tcp->tcp_rtdstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4224
		tcp->tcp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4225
		tcp->tcp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4226
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4227
	ASSERT(tcp->tcp_rtdstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4228
	if (tcp->tcp_rthdr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4229
		mi_free(tcp->tcp_rthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4230
		tcp->tcp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4231
		tcp->tcp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4232
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4233
	ASSERT(tcp->tcp_rthdrlen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4235
	ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4236
	if ((ipp->ipp_fields & (IPPF_HOPOPTS | IPPF_RTDSTOPTS |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4237
	    IPPF_DSTOPTS | IPPF_RTHDR)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4238
		if ((ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4239
			kmem_free(ipp->ipp_hopopts, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4240
			ipp->ipp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4241
			ipp->ipp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4242
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4243
		if ((ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4244
			kmem_free(ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4245
			ipp->ipp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4246
			ipp->ipp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4247
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4248
		if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4249
			kmem_free(ipp->ipp_dstopts, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4250
			ipp->ipp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4251
			ipp->ipp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4252
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4253
		if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4254
			kmem_free(ipp->ipp_rthdr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4255
			ipp->ipp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4256
			ipp->ipp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4257
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4258
		ipp->ipp_fields &= ~(IPPF_HOPOPTS | IPPF_RTDSTOPTS |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4259
		    IPPF_DSTOPTS | IPPF_RTHDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4260
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4261
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4262
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4263
	 * Free memory associated with the tcp/ip header template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4264
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4266
	if (tcp->tcp_iphc != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4267
		bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4269
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4270
	 * Following is really a blowing away a union.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4271
	 * It happens to have exactly two members of identical size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4272
	 * the following code is enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4273
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4274
	tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4276
	if (tcp->tcp_tracebuf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4277
		kmem_free(tcp->tcp_tracebuf, sizeof (tcptrch_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4278
		tcp->tcp_tracebuf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4279
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4280
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4283
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4284
 * Put a connection confirmation message upstream built from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4285
 * address information within 'iph' and 'tcph'.  Report our success or failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4286
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4287
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4288
tcp_conn_con(tcp_t *tcp, uchar_t *iphdr, tcph_t *tcph, mblk_t *idmp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4289
    mblk_t **defermp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4290
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4291
	sin_t	sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4292
	sin6_t	sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4293
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4294
	char	*optp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4295
	int	optlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4296
	cred_t	*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4298
	if (defermp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4299
		*defermp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4300
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4301
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4302
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4303
		 * Return in T_CONN_CON results of option negotiation through
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4304
		 * the T_CONN_REQ. Note: If there is an real end-to-end option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4305
		 * negotiation, then what is received from remote end needs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4306
		 * to be taken into account but there is no such thing (yet?)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4307
		 * in our TCP/IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4308
		 * Note: We do not use mi_offset_param() here as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4309
		 * tcp_opts_conn_req contents do not directly come from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4310
		 * an application and are either generated in kernel or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4311
		 * from user input that was already verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4312
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4313
		mp = tcp->tcp_conn.tcp_opts_conn_req;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4314
		optp = (char *)(mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4315
		    ((struct T_conn_req *)mp->b_rptr)->OPT_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4316
		optlen = (int)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4317
		    ((struct T_conn_req *)mp->b_rptr)->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4318
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4320
	if (IPH_HDR_VERSION(iphdr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4321
		ipha_t *ipha = (ipha_t *)iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4323
		/* packet is IPv4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4324
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4325
			sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4326
			sin.sin_addr.s_addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4327
			sin.sin_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4328
			sin.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4329
			mp = mi_tpi_conn_con(NULL, (char *)&sin,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4330
			    (int)sizeof (sin_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4331
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4332
			sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4333
			IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &sin6.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4334
			sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4335
			sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4336
			mp = mi_tpi_conn_con(NULL, (char *)&sin6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4337
			    (int)sizeof (sin6_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4339
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4340
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4341
		ip6_t	*ip6h = (ip6_t *)iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4343
		ASSERT(IPH_HDR_VERSION(iphdr) == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4344
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4345
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4346
		sin6.sin6_addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4347
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4348
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4349
		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4350
		mp = mi_tpi_conn_con(NULL, (char *)&sin6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4351
		    (int)sizeof (sin6_t), optp, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4352
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4354
	if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4355
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4357
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4358
		mblk_setcred(mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4359
		DB_CPID(mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4360
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4361
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4362
	if (defermp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4363
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4364
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4365
		*defermp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4367
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4368
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4369
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4370
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4371
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4372
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4373
 * Defense for the SYN attack -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4374
 * 1. When q0 is full, drop from the tail (tcp_eager_prev_q0) the oldest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4375
 *    one that doesn't have the dontdrop bit set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4376
 * 2. Don't drop a SYN request before its first timeout. This gives every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4377
 *    request at least til the first timeout to complete its 3-way handshake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4378
 * 3. Maintain tcp_syn_rcvd_timeout as an accurate count of how many
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4379
 *    requests currently on the queue that has timed out. This will be used
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4380
 *    as an indicator of whether an attack is under way, so that appropriate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4381
 *    actions can be taken. (It's incremented in tcp_timer() and decremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4382
 *    either when eager goes into ESTABLISHED, or gets freed up.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4383
 * 4. The current threshold is - # of timeout > q0len/4 => SYN alert on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4384
 *    # of timeout drops back to <= q0len/32 => SYN alert off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4385
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4386
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4387
tcp_drop_q0(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4388
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4389
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4391
	ASSERT(MUTEX_HELD(&tcp->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4392
	ASSERT(tcp->tcp_eager_next_q0 != tcp->tcp_eager_prev_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4393
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4394
	 * New one is added after next_q0 so prev_q0 points to the oldest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4395
	 * Also do not drop any established connections that are deferred on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4396
	 * q0 due to q being full
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4397
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4399
	eager = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4400
	while (eager->tcp_dontdrop || eager->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4401
		eager = eager->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4402
		if (eager == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4403
			eager = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4404
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4405
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4406
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4407
	if (eager->tcp_syn_rcvd_timeout == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4408
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4410
	if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4411
		(void) strlog(TCP_MOD_ID, 0, 3, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4412
		    "tcp_drop_q0: listen half-open queue (max=%d) overflow"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4413
		    " (%d pending) on %s, drop one", tcp_conn_req_max_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4414
		    tcp->tcp_conn_req_cnt_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4415
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4416
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4417
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4418
	BUMP_MIB(&tcp_mib, tcpHalfOpenDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4420
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4421
	 * need to do refhold here because the selected eager could
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4422
	 * be removed by someone else if we release the eager lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4423
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4424
	CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4425
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4426
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4427
	/* Mark the IRE created for this SYN request temporary */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4428
	tcp_ip_ire_mark_advice(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4429
	(void) tcp_clean_death(eager, ETIMEDOUT, 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4430
	CONN_DEC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4432
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4433
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4434
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4436
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4437
tcp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4438
    tcph_t *tcph, uint_t ipvers, mblk_t *idmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4439
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4440
	tcp_t 		*ltcp = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4441
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4442
	mblk_t		*tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4443
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4444
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4445
	sin6_t 		sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4446
	in6_addr_t 	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4447
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4448
	int		ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4449
	cred_t		*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4451
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4452
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4454
		connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4455
		connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4457
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_srcv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4458
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_remv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4460
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4461
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &sin6.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4462
		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4463
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4464
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4465
		sin6.__sin6_src_id = ip_srcid_find_addr(&v6dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4466
		    lconnp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4467
		if (tcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4468
			sin6_t	sin6d;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4470
			sin6d = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4471
			IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4472
			    &sin6d.sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4473
			sin6d.sin6_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4474
			sin6d.sin6_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4475
			tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4476
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4477
			    (char *)&tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4478
			    (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4479
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4480
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4481
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4482
			tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4483
			    (char *)&sin6, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4484
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4485
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4486
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4487
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4488
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4490
		connp->conn_send = ip_output_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4491
		connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4493
		connp->conn_srcv6 = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4494
		connp->conn_remv6 = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4496
		/* db_cksumstuff is set at ip_fanout_tcp_v6 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4497
		ifindex = (int)DB_CKSUMSTUFF(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4498
		DB_CKSUMSTUFF(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4500
		sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4501
		sin6.sin6_addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4502
		sin6.sin6_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4503
		sin6.sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4504
		sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4505
		sin6.__sin6_src_id = ip_srcid_find_addr(&ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4506
		    lconnp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4507
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4508
		if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4509
			/* Pass up the scope_id of remote addr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4510
			sin6.sin6_scope_id = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4511
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4512
			sin6.sin6_scope_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4513
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4514
		if (tcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4515
			sin6_t	sin6d;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4517
			sin6d = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4518
			sin6.sin6_addr = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4519
			sin6d.sin6_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4520
			sin6d.sin6_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4521
			tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4522
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4523
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4524
			    (char *)&sin6d, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4525
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4526
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4527
			tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4528
			    (char *)&sin6, sizeof (sin6_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4529
			    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4530
			    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4531
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4532
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4534
	if (tpi_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4535
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4536
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4537
	connp->conn_fport = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4538
	connp->conn_lport = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4539
	connp->conn_flags |= (IPCL_TCP6|IPCL_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4540
	connp->conn_fully_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4542
	if (tcp_trace)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4543
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4545
	/* Inherit information from the "parent" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4546
	tcp->tcp_ipversion = ltcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4547
	tcp->tcp_family = ltcp->tcp_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4548
	tcp->tcp_wq = ltcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4549
	tcp->tcp_rq = ltcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4550
	tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4551
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4552
	if ((err = tcp_init_values(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4553
		freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4554
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4555
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4557
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4558
		if ((err = tcp_header_init_ipv4(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4559
			freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4560
			return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4561
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4562
		ASSERT(tcp->tcp_ipha != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4563
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4564
		/* ifindex must be already set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4565
		ASSERT(ifindex != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4567
		if (ltcp->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4568
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4569
			 * Set newtcp's bound_if equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4570
			 * listener's value. If ifindex is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4571
			 * not the same as ltcp->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4572
			 * it must be a packet for the ipmp group
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4573
			 * of interfaces
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4574
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4575
			tcp->tcp_bound_if = ltcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4576
		} else if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4577
			tcp->tcp_bound_if = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4578
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4580
		tcp->tcp_ipv6_recvancillary = ltcp->tcp_ipv6_recvancillary;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4581
		tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4582
		tcp->tcp_recvhops = 0xffffffffU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4583
		ASSERT(tcp->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4584
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4586
	tcp->tcp_lport = ltcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4587
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4588
	if (ltcp->tcp_ipversion == tcp->tcp_ipversion) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4589
		if (tcp->tcp_iphc_len != ltcp->tcp_iphc_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4590
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4591
			 * Listener had options of some sort; eager inherits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4592
			 * Free up the eager template and allocate one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4593
			 * of the right size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4594
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4595
			if (tcp->tcp_hdr_grown) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4596
				kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4597
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4598
				bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4599
				kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4600
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4601
			tcp->tcp_iphc = kmem_zalloc(ltcp->tcp_iphc_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4602
			    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4603
			if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4604
				tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4605
				freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4606
				return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4607
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4608
			tcp->tcp_iphc_len = ltcp->tcp_iphc_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4609
			tcp->tcp_hdr_grown = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4610
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4611
		tcp->tcp_hdr_len = ltcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4612
		tcp->tcp_ip_hdr_len = ltcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4613
		tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4614
		tcp->tcp_ip6_hops = ltcp->tcp_ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4615
		tcp->tcp_ip6_vcf = ltcp->tcp_ip6_vcf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4616
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4617
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4618
		 * Copy the IP+TCP header template from listener to eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4619
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4620
		bcopy(ltcp->tcp_iphc, tcp->tcp_iphc, ltcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4621
		if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4622
			if (((ip6i_t *)(tcp->tcp_iphc))->ip6i_nxt ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4623
			    IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4624
				tcp->tcp_ip6h =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4625
				    (ip6_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4626
					sizeof (ip6i_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4627
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4628
				tcp->tcp_ip6h =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4629
				    (ip6_t *)(tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4630
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4631
			tcp->tcp_ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4632
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4633
			tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4634
			tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4635
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4636
		tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4637
		    tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4638
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4639
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4640
		 * only valid case when ipversion of listener and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4641
		 * eager differ is when listener is IPv6 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4642
		 * eager is IPv4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4643
		 * Eager header template has been initialized to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4644
		 * maximum v4 header sizes, which includes space for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4645
		 * TCP and IP options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4646
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4647
		ASSERT((ltcp->tcp_ipversion == IPV6_VERSION) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4648
		    (tcp->tcp_ipversion == IPV4_VERSION));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4649
		ASSERT(tcp->tcp_iphc_len >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4650
		    TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4651
		tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4652
		/* copy IP header fields individually */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4653
		tcp->tcp_ipha->ipha_ttl =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4654
		    ltcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4655
		bcopy(ltcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4656
		    tcp->tcp_tcph->th_lport, sizeof (ushort_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4657
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4659
	bcopy(tcph->th_lport, tcp->tcp_tcph->th_fport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4660
	bcopy(tcp->tcp_tcph->th_fport, &tcp->tcp_fport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4661
	    sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4663
	if (ltcp->tcp_lport == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4664
		tcp->tcp_lport = *(in_port_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4665
		bcopy(tcph->th_fport, tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4666
		    sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4667
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4669
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4670
		ASSERT(ipha != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4671
		tcp->tcp_ipha->ipha_dst = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4672
		tcp->tcp_ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4674
		/* Source routing option copyover (reverse it) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4675
		if (tcp_rev_src_routes)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4676
			tcp_opt_reverse(tcp, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4677
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4678
		ASSERT(ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4679
		tcp->tcp_ip6h->ip6_dst = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4680
		tcp->tcp_ip6h->ip6_src = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4681
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4682
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4683
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4684
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4685
	 * If the SYN contains a credential, it's a loopback packet; attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4686
	 * the credential to the TPI message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4687
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4688
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4689
		mblk_setcred(tpi_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4690
		DB_CPID(tpi_mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4691
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4692
	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4693
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4694
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4695
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4696
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4698
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4699
tcp_conn_create_v4(conn_t *lconnp, conn_t *connp, ipha_t *ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4700
    tcph_t *tcph, mblk_t *idmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4701
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4702
	tcp_t 		*ltcp = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4703
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4704
	sin_t		sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4705
	mblk_t		*tpi_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4706
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4707
	cred_t		*cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4708
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4709
	sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4710
	sin.sin_addr.s_addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4711
	sin.sin_port = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4712
	sin.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4713
	if (ltcp->tcp_recvdstaddr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4714
		sin_t	sind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4715
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4716
		sind = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4717
		sind.sin_addr.s_addr = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4718
		sind.sin_port = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4719
		sind.sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4720
		tpi_mp = mi_tpi_extconn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4721
		    (char *)&sind, sizeof (sin_t), (char *)&tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4722
		    (t_scalar_t)sizeof (intptr_t), (char *)&sind,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4723
		    sizeof (sin_t), (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4724
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4725
		tpi_mp = mi_tpi_conn_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4726
		    (char *)&sin, sizeof (sin_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4727
		    (char *)&tcp, (t_scalar_t)sizeof (intptr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4728
		    (t_scalar_t)ltcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4729
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4731
	if (tpi_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4732
		return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4733
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4735
	connp->conn_flags |= (IPCL_TCP4|IPCL_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4736
	connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4737
	connp->conn_recv = tcp_input;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4738
	connp->conn_fully_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4740
	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_srcv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4741
	IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_remv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4742
	connp->conn_fport = *(uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4743
	connp->conn_lport = *(uint16_t *)tcph->th_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4745
	if (tcp_trace) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4746
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4747
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4748
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4749
	/* Inherit information from the "parent" */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4750
	tcp->tcp_ipversion = ltcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4751
	tcp->tcp_family = ltcp->tcp_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4752
	tcp->tcp_wq = ltcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4753
	tcp->tcp_rq = ltcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4754
	tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4755
	tcp->tcp_detached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4756
	if ((err = tcp_init_values(tcp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4757
		freemsg(tpi_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4758
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4759
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4760
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4761
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4762
	 * Let's make sure that eager tcp template has enough space to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4763
	 * copy IPv4 listener's tcp template. Since the conn_t structure is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4764
	 * preserved and tcp_iphc_len is also preserved, an eager conn_t may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4765
	 * have a tcp_template of total len TCP_MAX_COMBINED_HEADER_LENGTH or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4766
	 * more (in case of re-allocation of conn_t with tcp-IPv6 template with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4767
	 * extension headers or with ip6i_t struct). Note that bcopy() below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4768
	 * copies listener tcp's hdr_len which cannot be greater than TCP_MAX_
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4769
	 * COMBINED_HEADER_LENGTH as this listener must be a IPv4 listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4770
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4771
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4772
	ASSERT(ltcp->tcp_hdr_len <= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4773
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4774
	tcp->tcp_hdr_len = ltcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4775
	tcp->tcp_ip_hdr_len = ltcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4776
	tcp->tcp_tcp_hdr_len = ltcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4777
	tcp->tcp_ttl = ltcp->tcp_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4778
	tcp->tcp_tos = ltcp->tcp_tos;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4780
	/* Copy the IP+TCP header template from listener to eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4781
	bcopy(ltcp->tcp_iphc, tcp->tcp_iphc, ltcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4782
	tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4783
	tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4784
	tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4785
	    tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4787
	/* Initialize the IP addresses and Ports */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4788
	tcp->tcp_ipha->ipha_dst = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4789
	tcp->tcp_ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4790
	bcopy(tcph->th_lport, tcp->tcp_tcph->th_fport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4791
	bcopy(tcph->th_fport, tcp->tcp_tcph->th_lport, sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4793
	/* Source routing option copyover (reverse it) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4794
	if (tcp_rev_src_routes)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4795
		tcp_opt_reverse(tcp, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4797
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4799
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4800
	 * If the SYN contains a credential, it's a loopback packet; attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4801
	 * the credential to the TPI message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4802
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4803
	if ((cr = DB_CRED(idmp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4804
		mblk_setcred(tpi_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4805
		DB_CPID(tpi_mp) = DB_CPID(idmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4806
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4807
	tcp->tcp_conn.tcp_eager_conn_ind = tpi_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4808
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4809
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4810
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4811
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4812
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4813
 * sets up conn for ipsec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4814
 * if the first mblk is M_CTL it is consumed and mpp is updated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4815
 * in case of error mpp is freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4816
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4817
conn_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4818
tcp_get_ipsec_conn(tcp_t *tcp, squeue_t *sqp, mblk_t **mpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4819
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4820
	conn_t 		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4821
	conn_t 		*econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4822
	squeue_t 	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4823
	mblk_t 		*first_mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4824
	mblk_t		*mp = *mpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4825
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4826
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4828
	econnp = tcp_get_conn(sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4829
	if (econnp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4830
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4831
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4832
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4833
	if (DB_TYPE(mp) == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4834
		if (mp->b_cont == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4835
		    mp->b_cont->b_datap->db_type != M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4836
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4837
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4838
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4839
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4840
		if ((mp->b_datap->db_struioflag & STRUIO_EAGER) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4841
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4842
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4843
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4845
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4846
		first_mp->b_datap->db_struioflag &= ~STRUIO_POLICY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4847
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4848
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4849
		ASSERT(mp->b_datap->db_struioflag & STRUIO_POLICY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4850
		mp->b_datap->db_struioflag &= ~STRUIO_POLICY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4852
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4853
	new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  4854
	DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4856
	ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4857
	ipvers = IPH_HDR_VERSION(mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4858
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4859
		uint16_t  	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4860
		uint32_t	ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4861
		ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4863
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4864
		up = (uint16_t *)((uchar_t *)ipha +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4865
		    IPH_HDR_LENGTH(ipha) + TCP_PORTS_OFFSET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4866
		ports = *(uint32_t *)up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4867
		IPCL_TCP_EAGER_INIT(econnp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4868
		    ipha->ipha_dst, ipha->ipha_src, ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4869
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4870
		uint16_t  	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4871
		uint32_t	ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4872
		uint16_t	ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4873
		uint8_t		*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4874
		ip6_t 		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4875
		tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4877
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4878
		if (ip6h->ip6_nxt == IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4879
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4880
		} else if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &ip_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4881
		    &nexthdrp) || *nexthdrp != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4882
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4883
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4884
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4885
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4886
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4887
		up = (uint16_t *)tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4888
		ports = *(uint32_t *)up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4889
		IPCL_TCP_EAGER_INIT_V6(econnp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4890
		    ip6h->ip6_dst, ip6h->ip6_src, ports);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4891
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4893
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4894
	 * The caller already ensured that there is a sqp present.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4895
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4896
	econnp->conn_sqp = new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4898
	if (connp->conn_policy != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4899
		ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4900
		ii = (ipsec_in_t *)(first_mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4901
		ASSERT(ii->ipsec_in_policy == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4902
		IPPH_REFHOLD(connp->conn_policy);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4903
		ii->ipsec_in_policy = connp->conn_policy;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4905
		first_mp->b_datap->db_type = IPSEC_POLICY_SET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4906
		if (!ip_bind_ipsec_policy_set(econnp, first_mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4907
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4908
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4909
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4910
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4911
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4912
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4913
	if (ipsec_conn_cache_policy(econnp, ipvers == IPV4_VERSION) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4914
		CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4915
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4916
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4917
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4919
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4920
	 * If we know we have some policy, pass the "IPSEC"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4921
	 * options size TCP uses this adjust the MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4922
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4923
	econnp->conn_tcp->tcp_ipsec_overhead = conn_ipsec_length(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4924
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4925
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4926
		*mpp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4927
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4929
	return (econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4930
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4931
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4932
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4933
 * tcp_get_conn/tcp_free_conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4934
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4935
 * tcp_get_conn is used to get a clean tcp connection structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4936
 * It tries to reuse the connections put on the freelist by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4937
 * time_wait_collector failing which it goes to kmem_cache. This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4938
 * way has two benefits compared to just allocating from and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4939
 * freeing to kmem_cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4940
 * 1) The time_wait_collector can free (which includes the cleanup)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4941
 * outside the squeue. So when the interrupt comes, we have a clean
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4942
 * connection sitting in the freelist. Obviously, this buys us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4943
 * performance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4944
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4945
 * 2) Defence against DOS attack. Allocating a tcp/conn in tcp_conn_request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4946
 * has multiple disadvantages - tying up the squeue during alloc, and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4947
 * fact that IPSec policy initialization has to happen here which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4948
 * requires us sending a M_CTL and checking for it i.e. real ugliness.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4949
 * But allocating the conn/tcp in IP land is also not the best since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4950
 * we can't check the 'q' and 'q0' which are protected by squeue and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4951
 * blindly allocate memory which might have to be freed here if we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4952
 * not allowed to accept the connection. By using the freelist and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4953
 * putting the conn/tcp back in freelist, we don't pay a penalty for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4954
 * allocating memory without checking 'q/q0' and freeing it if we can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4955
 * accept the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4956
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4957
 * Care should be taken to put the conn back in the same squeue's freelist
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4958
 * from which it was allocated. Best results are obtained if conn is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4959
 * allocated from listener's squeue and freed to the same. Time wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4960
 * collector will free up the freelist is the connection ends up sitting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4961
 * there for too long.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4962
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4963
void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4964
tcp_get_conn(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4965
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4966
	tcp_t			*tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4967
	conn_t			*connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4968
	squeue_t		*sqp = (squeue_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4969
	tcp_squeue_priv_t 	*tcp_time_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4971
	tcp_time_wait =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4972
	    *((tcp_squeue_priv_t **)squeue_getprivate(sqp, SQPRIVATE_TCP));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4973
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4974
	mutex_enter(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4975
	tcp = tcp_time_wait->tcp_free_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4976
	if (tcp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4977
		tcp_time_wait->tcp_free_list = tcp->tcp_time_wait_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4978
		mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4979
		tcp->tcp_time_wait_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4980
		connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4981
		connp->conn_flags |= IPCL_REUSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4982
		return ((void *)connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4983
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4984
	mutex_exit(&tcp_time_wait->tcp_time_wait_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4985
	if ((connp = ipcl_conn_create(IPCL_TCPCONN, KM_NOSLEEP)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4986
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4987
	return ((void *)connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4988
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4989
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4990
/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4991
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4992
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4993
 * The sockfs ACCEPT path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4994
 * =======================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4995
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4996
 * The eager is now established in its own perimeter as soon as SYN is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4997
 * received in tcp_conn_request(). When sockfs receives conn_ind, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4998
 * completes the accept processing on the acceptor STREAM. The sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  4999
 * of conn_ind part is common for both sockfs listener and a TLI/XTI
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5000
 * listener but a TLI/XTI listener completes the accept processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5001
 * on the listener perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5002
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5003
 * Common control flow for 3 way handshake:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5004
 * ----------------------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5005
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5006
 * incoming SYN (listener perimeter) 	-> tcp_rput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5007
 *					-> tcp_conn_request()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5008
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5009
 * incoming SYN-ACK-ACK (eager perim) 	-> tcp_rput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5010
 * send T_CONN_IND (listener perim)	-> tcp_send_conn_ind()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5011
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5012
 * Sockfs ACCEPT Path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5013
 * -------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5014
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5015
 * open acceptor stream (ip_tcpopen allocates tcp_wput_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5016
 * as STREAM entry point)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5017
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5018
 * soaccept() sends T_CONN_RES on the acceptor STREAM to tcp_wput_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5019
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5020
 * tcp_wput_accept() extracts the eager and makes the q->q_ptr <-> eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5021
 * association (we are not behind eager's squeue but sockfs is protecting us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5022
 * and no one knows about this stream yet. The STREAMS entry point q->q_info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5023
 * is changed to point at tcp_wput().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5024
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5025
 * tcp_wput_accept() sends any deferred eagers via tcp_send_pending() to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5026
 * listener (done on listener's perimeter).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5027
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5028
 * tcp_wput_accept() calls tcp_accept_finish() on eagers perimeter to finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5029
 * accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5030
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5031
 * TLI/XTI client ACCEPT path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5032
 * ---------------------------
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5033
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5034
 * soaccept() sends T_CONN_RES on the listener STREAM.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5035
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5036
 * tcp_accept() -> tcp_accept_swap() complete the processing and send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5037
 * the bind_mp to eager perimeter to finish accept (tcp_rput_other()).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5038
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5039
 * Locks:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5040
 * ======
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5041
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5042
 * listener->tcp_eager_lock protects the listeners->tcp_eager_next_q0 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5043
 * and listeners->tcp_eager_next_q.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5044
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5045
 * Referencing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5046
 * ============
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5047
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5048
 * 1) We start out in tcp_conn_request by eager placing a ref on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5049
 * listener and listener adding eager to listeners->tcp_eager_next_q0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5050
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5051
 * 2) When a SYN-ACK-ACK arrives, we send the conn_ind to listener. Before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5052
 * doing so we place a ref on the eager. This ref is finally dropped at the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5053
 * end of tcp_accept_finish() while unwinding from the squeue, i.e. the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5054
 * reference is dropped by the squeue framework.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5055
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5056
 * 3) The ref on listener placed in 1 above is dropped in tcp_accept_finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5057
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5058
 * The reference must be released by the same entity that added the reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5059
 * In the above scheme, the eager is the entity that adds and releases the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5060
 * references. Note that tcp_accept_finish executes in the squeue of the eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5061
 * (albeit after it is attached to the acceptor stream). Though 1. executes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5062
 * in the listener's squeue, the eager is nascent at this point and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5063
 * reference can be considered to have been added on behalf of the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5064
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5065
 * Eager getting a Reset or listener closing:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5066
 * ==========================================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5067
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5068
 * Once the listener and eager are linked, the listener never does the unlink.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5069
 * If the listener needs to close, tcp_eager_cleanup() is called which queues
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5070
 * a message on all eager perimeter. The eager then does the unlink, clears
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5071
 * any pointers to the listener's queue and drops the reference to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5072
 * listener. The listener waits in tcp_close outside the squeue until its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5073
 * refcount has dropped to 1. This ensures that the listener has waited for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5074
 * all eagers to clear their association with the listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5075
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5076
 * Similarly, if eager decides to go away, it can unlink itself and close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5077
 * When the T_CONN_RES comes down, we check if eager has closed. Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5078
 * the reference to eager is still valid because of the extra ref we put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5079
 * in tcp_send_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5080
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5081
 * Listener can always locate the eager under the protection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5082
 * of the listener->tcp_eager_lock, and then do a refhold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5083
 * on the eager during the accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5084
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5085
 * The acceptor stream accesses the eager in the accept processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5086
 * based on the ref placed on eager before sending T_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5087
 * The only entity that can negate this refhold is a listener close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5088
 * which is mutually exclusive with an active acceptor stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5089
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5090
 * Eager's reference on the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5091
 * ===================================
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5092
 * 
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5093
 * If the accept happens (even on a closed eager) the eager drops its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5094
 * reference on the listener at the start of tcp_accept_finish. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5095
 * eager is killed due to an incoming RST before the T_conn_ind is sent up,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5096
 * the reference is dropped in tcp_closei_local. If the listener closes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5097
 * the reference is dropped in tcp_eager_kill. In all cases the reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5098
 * is dropped while executing in the eager's context (squeue).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5099
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5100
/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5102
/* Process the SYN packet, mp, directed at the listener 'tcp' */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5104
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5105
 * THIS FUNCTION IS DIRECTLY CALLED BY IP VIA SQUEUE FOR SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5106
 * tcp_rput_data will not see any SYN packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5107
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5108
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5109
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5110
tcp_conn_request(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5111
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5112
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5113
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5114
	tcp_t		*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5115
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5116
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5117
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5118
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5119
	conn_t		*econnp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5120
	squeue_t	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5121
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5122
	uint_t 		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5123
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5124
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5125
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5127
	if (tcp->tcp_state != TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5128
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5130
	ASSERT((tcp->tcp_connp->conn_flags & IPCL_BOUND) != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5132
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5133
	if (tcp->tcp_conn_req_cnt_q >= tcp->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5134
		mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5135
		TCP_STAT(tcp_listendrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5136
		BUMP_MIB(&tcp_mib, tcpListenDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5137
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5138
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5139
			    "tcp_conn_request: listen backlog (max=%d) "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5140
			    "overflow (%d pending) on %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5141
			    tcp->tcp_conn_req_max, tcp->tcp_conn_req_cnt_q,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5142
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5143
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5144
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5145
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5147
	if (tcp->tcp_conn_req_cnt_q0 >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5148
	    tcp->tcp_conn_req_max + tcp_conn_req_max_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5149
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5150
		 * Q0 is full. Drop a pending half-open req from the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5151
		 * to make room for the new SYN req. Also mark the time we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5152
		 * drop a SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5153
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5154
		 * A more aggressive defense against SYN attack will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5155
		 * be to set the "tcp_syn_defense" flag now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5156
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5157
		TCP_STAT(tcp_listendropq0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5158
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5159
		if (!tcp_drop_q0(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5160
			mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5161
			BUMP_MIB(&tcp_mib, tcpListenDropQ0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5162
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5163
				(void) strlog(TCP_MOD_ID, 0, 3, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5164
				    "tcp_conn_request: listen half-open queue "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5165
				    "(max=%d) full (%d pending) on %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5166
				    tcp_conn_req_max_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5167
				    tcp->tcp_conn_req_cnt_q0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5168
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5169
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5170
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5171
			goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5172
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5173
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5174
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5176
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5177
	 * IP adds STRUIO_EAGER and ensures that the received packet is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5178
	 * M_DATA even if conn_ipv6_recvpktinfo is enabled or for ip6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5179
	 * link local address.  If IPSec is enabled, db_struioflag has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5180
	 * STRUIO_POLICY set (mutually exclusive from STRUIO_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5181
	 * otherwise an error case if neither of them is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5182
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5183
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5184
		new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5185
		DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5186
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5187
		econnp = (conn_t *)tcp_get_conn(arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5188
		if (econnp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5189
			goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5190
		econnp->conn_sqp = new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5191
	} else if ((mp->b_datap->db_struioflag & STRUIO_POLICY) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5192
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5193
		 * mp is updated in tcp_get_ipsec_conn().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5194
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5195
		econnp = tcp_get_ipsec_conn(tcp, arg2, &mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5196
		if (econnp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5197
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5198
			 * mp freed by tcp_get_ipsec_conn.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5199
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5200
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5201
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5202
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5203
		goto error2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5204
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5205
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5206
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5208
	ipvers = IPH_HDR_VERSION(mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5209
	ASSERT(ipvers == IPV6_VERSION || ipvers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5210
	ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5211
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5212
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5213
		ip_hdr_len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5214
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5215
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5216
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5217
		ip_hdr_len = ip_hdr_length_v6(mp, ip6h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5218
		tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5219
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5221
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5222
		ASSERT(ipvers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5223
		err = tcp_conn_create_v4(connp, econnp, ipha, tcph, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5224
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5225
		err = tcp_conn_create_v6(connp, econnp, mp, tcph, ipvers, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5226
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5228
	if (err)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5229
		goto error3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5231
	eager = econnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5233
	/* Inherit various TCP parameters from the listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5234
	eager->tcp_naglim = tcp->tcp_naglim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5235
	eager->tcp_first_timer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5236
	    tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5237
	eager->tcp_second_timer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5238
	    tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5240
	eager->tcp_first_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5241
	    tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5242
	eager->tcp_second_ctimer_threshold =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5243
	    tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5245
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5246
	 * Zones: tcp_adapt_ire() and tcp_send_data() both need the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5247
	 * zone id before the accept is completed in tcp_wput_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5248
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5249
	econnp->conn_zoneid = connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5251
	eager->tcp_hard_binding = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5253
	tcp_bind_hash_insert(&tcp_bind_fanout[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5254
	    TCP_BIND_HASH(eager->tcp_lport)], eager, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5256
	CL_INET_CONNECT(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5258
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5259
	 * No need to check for multicast destination since ip will only pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5260
	 * up multicasts to those that have expressed interest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5261
	 * TODO: what about rejecting broadcasts?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5262
	 * Also check that source is not a multicast or broadcast address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5263
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5264
	eager->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5265
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5266
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5267
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5268
	 * There should be no ire in the mp as we are being called after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5269
	 * receiving the SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5270
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5271
	ASSERT(tcp_ire_mp(mp) == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5274
	 * Adapt our mss, ttl, ... according to information provided in IRE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5275
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5277
	if (tcp_adapt_ire(eager, NULL) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5278
		/* Undo the bind_hash_insert */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5279
		tcp_bind_hash_remove(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5280
		goto error3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5281
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5283
	/* Process all TCP options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5284
	tcp_process_options(eager, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5286
	/* Is the other end ECN capable? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5287
	if (tcp_ecn_permitted >= 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5288
	    (tcph->th_flags[0] & (TH_ECE|TH_CWR)) == (TH_ECE|TH_CWR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5289
		eager->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5290
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5292
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5293
	 * listener->tcp_rq->q_hiwat should be the default window size or a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5294
	 * window size changed via SO_RCVBUF option.  First round up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5295
	 * eager's tcp_rwnd to the nearest MSS.  Then find out the window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5296
	 * scale option value if needed.  Call tcp_rwnd_set() to finish the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5297
	 * setting.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5298
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5299
	 * Note if there is a rpipe metric associated with the remote host,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5300
	 * we should not inherit receive window size from listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5301
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5302
	eager->tcp_rwnd = MSS_ROUNDUP(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5303
	    (eager->tcp_rwnd == 0 ? tcp->tcp_rq->q_hiwat :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5304
	    eager->tcp_rwnd), eager->tcp_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5305
	if (eager->tcp_snd_ws_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5306
		tcp_set_ws_value(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5307
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5308
	 * Note that this is the only place tcp_rwnd_set() is called for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5309
	 * accepting a connection.  We need to call it here instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5310
	 * after the 3-way handshake because we need to tell the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5311
	 * side our rwnd in the SYN-ACK segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5312
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5313
	(void) tcp_rwnd_set(eager, eager->tcp_rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5315
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5316
	 * We eliminate the need for sockfs to send down a T_SVR4_OPTMGMT_REQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5317
	 * via soaccept()->soinheritoptions() which essentially applies
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5318
	 * all the listener options to the new STREAM. The options that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5319
	 * need to take care of are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5320
	 * SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5321
	 * SO_USELOOPBACK, SO_OOBINLINE, SO_DGRAM_ERRIND, SO_LINGER,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5322
	 * SO_SNDBUF, SO_RCVBUF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5323
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5324
	 * SO_RCVBUF:	tcp_rwnd_set() above takes care of it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5325
	 * SO_SNDBUF:	Set the tcp_xmit_hiwater for the eager. When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5326
	 *		tcp_maxpsz_set() gets called later from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5327
	 *		tcp_accept_finish(), the option takes effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5328
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5329
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5330
	/* Set the TCP options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5331
	eager->tcp_xmit_hiwater = tcp->tcp_xmit_hiwater;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5332
	eager->tcp_dgram_errind = tcp->tcp_dgram_errind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5333
	eager->tcp_oobinline = tcp->tcp_oobinline;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5334
	eager->tcp_reuseaddr = tcp->tcp_reuseaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5335
	eager->tcp_broadcast = tcp->tcp_broadcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5336
	eager->tcp_useloopback = tcp->tcp_useloopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5337
	eager->tcp_dontroute = tcp->tcp_dontroute;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5338
	eager->tcp_linger = tcp->tcp_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5339
	eager->tcp_lingertime = tcp->tcp_lingertime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5340
	if (tcp->tcp_ka_enabled)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5341
		eager->tcp_ka_enabled = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5342
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5343
	/* Set the IP options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5344
	econnp->conn_broadcast = connp->conn_broadcast;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5345
	econnp->conn_loopback = connp->conn_loopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5346
	econnp->conn_dontroute = connp->conn_dontroute;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5347
	econnp->conn_reuseaddr = connp->conn_reuseaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5349
	/* Put a ref on the listener for the eager. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5350
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5351
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5352
	tcp->tcp_eager_next_q0->tcp_eager_prev_q0 = eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5353
	eager->tcp_eager_next_q0 = tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5354
	tcp->tcp_eager_next_q0 = eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5355
	eager->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5357
	/* Set tcp_listener before adding it to tcp_conn_fanout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5358
	eager->tcp_listener = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5359
	eager->tcp_saved_listener = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5361
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5362
	 * Tag this detached tcp vector for later retrieval
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5363
	 * by our listener client in tcp_accept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5364
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5365
	eager->tcp_conn_req_seqnum = tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5366
	tcp->tcp_conn_req_cnt_q0++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5367
	if (++tcp->tcp_conn_req_seqnum == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5368
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5369
		 * -1 is "special" and defined in TPI as something
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5370
		 * that should never be used in T_CONN_IND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5371
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5372
		++tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5373
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5374
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5376
	if (tcp->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5377
		/* Don't drop the SYN that comes from a good IP source */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5378
		ipaddr_t *addr_cache = (ipaddr_t *)(tcp->tcp_ip_addr_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5379
		if (addr_cache != NULL && eager->tcp_remote ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5380
		    addr_cache[IP_ADDR_CACHE_HASH(eager->tcp_remote)]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5381
			eager->tcp_dontdrop = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5382
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5383
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5385
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5386
	 * We need to insert the eager in its own perimeter but as soon
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5387
	 * as we do that, we expose the eager to the classifier and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5388
	 * should not touch any field outside the eager's perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5389
	 * So do all the work necessary before inserting the eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5390
	 * in its own perimeter. Be optimistic that ipcl_conn_insert()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5391
	 * will succeed but undo everything if it fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5392
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5393
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5394
	eager->tcp_irs = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5395
	eager->tcp_rack = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5396
	eager->tcp_rnxt = seg_seq + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5397
	U32_TO_ABE32(eager->tcp_rnxt, eager->tcp_tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5398
	BUMP_MIB(&tcp_mib, tcpPassiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5399
	eager->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5400
	mp1 = tcp_xmit_mp(eager, eager->tcp_xmit_head, eager->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5401
	    NULL, NULL, eager->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5402
	if (mp1 == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5403
		goto error1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5404
	mblk_setcred(mp1, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5405
	DB_CPID(mp1) = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5407
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5408
	 * We need to start the rto timer. In normal case, we start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5409
	 * the timer after sending the packet on the wire (or at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5410
	 * least believing that packet was sent by waiting for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5411
	 * CALL_IP_WPUT() to return). Since this is the first packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5412
	 * being sent on the wire for the eager, our initial tcp_rto
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5413
	 * is at least tcp_rexmit_interval_min which is a fairly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5414
	 * large value to allow the algorithm to adjust slowly to large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5415
	 * fluctuations of RTT during first few transmissions.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5416
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5417
	 * Starting the timer first and then sending the packet in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5418
	 * case shouldn't make much difference since tcp_rexmit_interval_min
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5419
	 * is of the order of several 100ms and starting the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5420
	 * first and then sending the packet will result in difference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5421
	 * of few micro seconds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5422
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5423
	 * Without this optimization, we are forced to hold the fanout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5424
	 * lock across the ipcl_bind_insert() and sending the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5425
	 * so that we don't race against an incoming packet (maybe RST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5426
	 * for this eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5427
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5429
	TCP_RECORD_TRACE(eager, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5430
	TCP_TIMER_RESTART(eager, eager->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5433
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5434
	 * Insert the eager in its own perimeter now. We are ready to deal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5435
	 * with any packets on eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5436
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5437
	if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5438
		if (ipcl_conn_insert(econnp, IPPROTO_TCP, 0, 0, 0) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5439
			goto error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5440
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5441
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5442
		if (ipcl_conn_insert_v6(econnp, IPPROTO_TCP, 0, 0, 0, 0) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5443
			goto error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5444
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5445
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5447
	/* mark conn as fully-bound */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5448
	econnp->conn_fully_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5450
	/* Send the SYN-ACK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5451
	tcp_send_data(eager, eager->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5452
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5454
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5455
error:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5456
	(void) TCP_TIMER_CANCEL(eager, eager->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5457
	freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5458
error1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5459
	/* Undo what we did above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5460
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5461
	tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5462
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5463
	/* Drop eager's reference on the listener */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5464
	CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5466
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5467
	 * Delete the cached ire in conn_ire_cache and also mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5468
	 * the conn as CONDEMNED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5469
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5470
	mutex_enter(&econnp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5471
	econnp->conn_state_flags |= CONN_CONDEMNED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5472
	ire = econnp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5473
	econnp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5474
	mutex_exit(&econnp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5475
	if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5476
		IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5478
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5479
	 * tcp_accept_comm inserts the eager to the bind_hash
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5480
	 * we need to remove it from the hash if ipcl_conn_insert
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5481
	 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5482
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5483
	tcp_bind_hash_remove(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5484
	/* Drop the eager ref placed in tcp_open_detached */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5485
	CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5487
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5488
	 * If a connection already exists, send the mp to that connections so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5489
	 * that it can be appropriately dealt with.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5490
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5491
	if ((econnp = ipcl_classify(mp, connp->conn_zoneid)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5492
		if (!IPCL_IS_CONNECTED(econnp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5493
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5494
			 * Something bad happened. ipcl_conn_insert()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5495
			 * failed because a connection already existed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5496
			 * in connected hash but we can't find it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5497
			 * anymore (someone blew it away). Just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5498
			 * free this message and hopefully remote
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5499
			 * will retransmit at which time the SYN can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5500
			 * treated as a new connection or dealth with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5501
			 * a TH_RST if a connection already exists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5502
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5503
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5504
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5505
			squeue_fill(econnp->conn_sqp, mp, tcp_input,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5506
			    econnp, SQTAG_TCP_CONN_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5507
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5508
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5509
		/* Nobody wants this packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5510
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5511
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5512
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5513
error2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5514
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5515
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5516
error3:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5517
	CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5518
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5519
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5520
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5521
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5522
 * In an ideal case of vertical partition in NUMA architecture, its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5523
 * beneficial to have the listener and all the incoming connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5524
 * tied to the same squeue. The other constraint is that incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5525
 * connections should be tied to the squeue attached to interrupted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5526
 * CPU for obvious locality reason so this leaves the listener to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5527
 * be tied to the same squeue. Our only problem is that when listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5528
 * is binding, the CPU that will get interrupted by the NIC whose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5529
 * IP address the listener is binding to is not even known. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5530
 * the code below allows us to change that binding at the time the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5531
 * CPU is interrupted by virtue of incoming connection's squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5532
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5533
 * This is usefull only in case of a listener bound to a specific IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5534
 * address. For other kind of listeners, they get bound the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5535
 * very first time and there is no attempt to rebind them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5536
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5537
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5538
tcp_conn_request_unbound(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5539
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5540
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5541
	squeue_t	*sqp = (squeue_t *)arg2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5542
	squeue_t	*new_sqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5543
	uint32_t	conn_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5545
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  5546
		new_sqp = (squeue_t *)DB_CKSUMSTART(mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5547
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5548
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5549
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5550
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5551
	if (connp->conn_fanout == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5552
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5554
	if (!(connp->conn_flags & IPCL_FULLY_BOUND)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5555
		mutex_enter(&connp->conn_fanout->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5556
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5557
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5558
		 * No one from read or write side can access us now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5559
		 * except for already queued packets on this squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5560
		 * But since we haven't changed the squeue yet, they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5561
		 * can't execute. If they are processed after we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5562
		 * changed the squeue, they are sent back to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5563
		 * correct squeue down below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5564
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5565
		if (connp->conn_sqp != new_sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5566
			while (connp->conn_sqp != new_sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5567
				(void) casptr(&connp->conn_sqp, sqp, new_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5568
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5570
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5571
			conn_flags = connp->conn_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5572
			conn_flags |= IPCL_FULLY_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5573
			(void) cas32(&connp->conn_flags, connp->conn_flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5574
			    conn_flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5575
		} while (!(connp->conn_flags & IPCL_FULLY_BOUND));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5577
		mutex_exit(&connp->conn_fanout->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5578
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5579
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5581
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5582
	if (connp->conn_sqp != sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5583
		CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5584
		squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5585
		    connp->conn_recv, connp, SQTAG_TCP_CONN_REQ_UNBOUND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5586
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5587
		tcp_conn_request(connp, mp, sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5588
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5589
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5591
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5592
 * Successful connect request processing begins when our client passes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5593
 * a T_CONN_REQ message into tcp_wput() and ends when tcp_rput() passes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5594
 * our T_OK_ACK reply message upstream.  The control flow looks like this:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5595
 *   upstream -> tcp_wput() -> tcp_wput_proto() -> tcp_connect() -> IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5596
 *   upstream <- tcp_rput()                <- IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5597
 * After various error checks are completed, tcp_connect() lays
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5598
 * the target address and port into the composite header template,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5599
 * preallocates the T_OK_ACK reply message, construct a full 12 byte bind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5600
 * request followed by an IRE request, and passes the three mblk message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5601
 * down to IP looking like this:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5602
 *   O_T_BIND_REQ for IP  --> IRE req --> T_OK_ACK for our client
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5603
 * Processing continues in tcp_rput() when we receive the following message:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5604
 *   T_BIND_ACK from IP --> IRE ack --> T_OK_ACK for our client
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5605
 * After consuming the first two mblks, tcp_rput() calls tcp_timer(),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5606
 * to fire off the connection request, and then passes the T_OK_ACK mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5607
 * upstream that we filled in below.  There are, of course, numerous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5608
 * error conditions along the way which truncate the processing described
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5609
 * above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5610
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5611
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5612
tcp_connect(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5613
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5614
	sin_t		*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5615
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5616
	queue_t		*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5617
	struct T_conn_req	*tcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5618
	ipaddr_t	*dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5619
	in_port_t	dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5620
	uint_t		srcid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5622
	tcr = (struct T_conn_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5624
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5625
	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5626
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5627
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5628
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5630
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5631
	 * Determine packet type based on type of address passed in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5632
	 * the request should contain an IPv4 or IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5633
	 * Make sure that address family matches the type of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5634
	 * family of the the address passed down
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5635
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5636
	switch (tcr->DEST_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5637
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5638
		tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5639
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5641
	case (sizeof (sin_t) - sizeof (sin->sin_zero)): {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5642
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5643
		 * XXX: The check for valid DEST_length was not there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5644
		 * in earlier releases and some buggy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5645
		 * TLI apps (e.g Sybase) got away with not feeding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5646
		 * in sin_zero part of address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5647
		 * We allow that bug to keep those buggy apps humming.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5648
		 * Test suites require the check on DEST_length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5649
		 * We construct a new mblk with valid DEST_length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5650
		 * free the original so the rest of the code does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5651
		 * not have to keep track of this special shorter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5652
		 * length address case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5653
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5654
		mblk_t *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5655
		struct T_conn_req *ntcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5656
		sin_t *nsin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5658
		nmp = allocb(sizeof (struct T_conn_req) + sizeof (sin_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5659
		    tcr->OPT_length, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5660
		if (nmp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5661
			tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5662
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5663
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5664
		ntcr = (struct T_conn_req *)nmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5665
		bzero(ntcr, sizeof (struct T_conn_req)); /* zero fill */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5666
		ntcr->PRIM_type = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5667
		ntcr->DEST_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5668
		ntcr->DEST_offset = sizeof (struct T_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5669
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5670
		nsin = (sin_t *)((uchar_t *)ntcr + ntcr->DEST_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5671
		*nsin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5672
		/* Get pointer to shorter address to copy from original mp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5673
		sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5674
		    tcr->DEST_length); /* extract DEST_length worth of sin_t */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5675
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5676
			freemsg(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5677
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5678
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5679
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5680
		nsin->sin_family = sin->sin_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5681
		nsin->sin_port = sin->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5682
		nsin->sin_addr = sin->sin_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5683
		/* Note:nsin->sin_zero zero-fill with sin_null assign above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5684
		nmp->b_wptr = (uchar_t *)&nsin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5685
		if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5686
			ntcr->OPT_length = tcr->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5687
			ntcr->OPT_offset = nmp->b_wptr - nmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5688
			bcopy((uchar_t *)tcr + tcr->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5689
			    (uchar_t *)ntcr + ntcr->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5690
			    tcr->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5691
			nmp->b_wptr += tcr->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5692
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5693
		freemsg(mp);	/* original mp freed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5694
		mp = nmp;	/* re-initialize original variables */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5695
		tcr = ntcr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5696
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5697
	/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5698
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5699
	case sizeof (sin_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5700
		sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5701
		    sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5702
		if (sin == NULL || !OK_32PTR((char *)sin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5703
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5704
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5705
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5706
		if (tcp->tcp_family != AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5707
		    sin->sin_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5708
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5709
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5710
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5711
		if (sin->sin_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5712
			tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5713
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5714
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5715
		if (tcp->tcp_connp && tcp->tcp_connp->conn_ipv6_v6only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5716
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5717
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5718
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5720
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5722
	case sizeof (sin6_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5723
		sin6 = (sin6_t *)mi_offset_param(mp, tcr->DEST_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5724
		    sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5725
		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5726
			tcp_err_ack(tcp, mp, TSYSERR, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5727
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5728
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5729
		if (tcp->tcp_family != AF_INET6 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5730
		    sin6->sin6_family != AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5731
			tcp_err_ack(tcp, mp, TSYSERR, EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5732
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5733
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5734
		if (sin6->sin6_port == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5735
			tcp_err_ack(tcp, mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5736
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5738
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5739
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5740
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5741
	 * TODO: If someone in TCPS_TIME_WAIT has this dst/port we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5742
	 * should key on their sequence number and cut them loose.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5743
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5745
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5746
	 * If options passed in, feed it for verification and handling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5747
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5748
	if (tcr->OPT_length != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5749
		mblk_t	*ok_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5750
		mblk_t	*discon_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5751
		mblk_t  *conn_opts_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5752
		int t_error, sys_error, do_disconnect;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5754
		conn_opts_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5756
		if (tcp_conprim_opt_process(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5757
			&do_disconnect, &t_error, &sys_error) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5758
			if (do_disconnect) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5759
				ASSERT(t_error == 0 && sys_error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5760
				discon_mp = mi_tpi_discon_ind(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5761
				    ECONNREFUSED, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5762
				if (!discon_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5763
					tcp_err_ack_prim(tcp, mp, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5764
					    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5765
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5766
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5767
				ok_mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5768
				if (!ok_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5769
					tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5770
					    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5771
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5772
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5773
				qreply(q, ok_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5774
				qreply(q, discon_mp); /* no flush! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5775
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5776
				ASSERT(t_error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5777
				tcp_err_ack_prim(tcp, mp, T_CONN_REQ, t_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5778
				    sys_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5779
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5780
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5781
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5782
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5783
		 * Success in setting options, the mp option buffer represented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5784
		 * by OPT_length/offset has been potentially modified and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5785
		 * contains results of option processing. We copy it in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5786
		 * another mp to save it for potentially influencing returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5787
		 * it in T_CONN_CONN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5788
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5789
		if (tcr->OPT_length != 0) { /* there are resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5790
			conn_opts_mp = copyb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5791
			if (!conn_opts_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5792
				tcp_err_ack_prim(tcp, mp, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5793
				    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5794
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5795
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5796
			ASSERT(tcp->tcp_conn.tcp_opts_conn_req == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5797
			tcp->tcp_conn.tcp_opts_conn_req = conn_opts_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5798
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5799
			 * Note:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5800
			 * These resulting option negotiation can include any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5801
			 * end-to-end negotiation options but there no such
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5802
			 * thing (yet?) in our TCP/IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5803
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5804
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5805
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5807
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5808
	 * If we're connecting to an IPv4-mapped IPv6 address, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5809
	 * make sure that the template IP header in the tcp structure is an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5810
	 * IPv4 header, and that the tcp_ipversion is IPV4_VERSION.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5811
	 * need to this before we call tcp_bindi() so that the port lookup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5812
	 * code will look for ports in the correct port space (IPv4 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5813
	 * IPv6 have separate port spaces).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5814
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5815
	if (tcp->tcp_family == AF_INET6 && tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5816
	    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5817
		int err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5818
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5819
		err = tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5820
		if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5821
			mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5822
			goto connect_failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5823
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5824
		if (tcp->tcp_lport != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5825
			*(uint16_t *)tcp->tcp_tcph->th_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5826
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5828
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5829
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5830
		/*
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5831
		 * We support quick connect, refer to comments in
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5832
		 * tcp_connect_*()
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5833
		 */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5834
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5835
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5836
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5837
		if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5838
			if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5839
				tcp_connect_ipv6(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5840
				    &sin6->sin6_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5841
				    sin6->sin6_port, sin6->sin6_flowinfo,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5842
				    sin6->__sin6_src_id, sin6->sin6_scope_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5843
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5844
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5845
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5846
			 * Destination adress is mapped IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5847
			 * Source bound address should be unspecified or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5848
			 * IPv6 mapped address as well.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5849
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5850
			if (!IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5851
			    &tcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5852
			    !IN6_IS_ADDR_V4MAPPED(&tcp->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5853
				mp = mi_tpi_err_ack_alloc(mp, TSYSERR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5854
				    EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5855
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5856
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5857
			dstaddrp = &V4_PART_OF_V6((sin6->sin6_addr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5858
			dstport = sin6->sin6_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5859
			srcid = sin6->__sin6_src_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5860
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5861
			dstaddrp = &sin->sin_addr.s_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5862
			dstport = sin->sin_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5863
			srcid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5864
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5866
		tcp_connect_ipv4(tcp, mp, dstaddrp, dstport, srcid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5867
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5868
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5869
		mp = mi_tpi_err_ack_alloc(mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5870
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5871
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5872
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5873
	 * Note: Code below is the "failure" case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5874
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5875
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5876
connect_failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5877
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5878
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5879
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5880
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5881
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5882
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5883
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5884
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5885
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5887
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5888
 * Handle connect to IPv4 destinations, including connections for AF_INET6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5889
 * sockets connecting to IPv4 mapped IPv6 destinations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5890
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5891
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5892
tcp_connect_ipv4(tcp_t *tcp, mblk_t *mp, ipaddr_t *dstaddrp, in_port_t dstport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5893
    uint_t srcid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5894
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5895
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5896
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5897
	ipaddr_t dstaddr = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5898
	int32_t	oldstate;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5899
	uint16_t lport;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5901
	ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5903
	/* Check for attempt to connect to INADDR_ANY */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5904
	if (dstaddr == INADDR_ANY)  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5905
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5906
		 * SunOS 4.x and 4.3 BSD allow an application
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5907
		 * to connect a TCP socket to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5908
		 * When they do this, the kernel picks the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5909
		 * address of one interface and uses it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5910
		 * instead.  The kernel usually ends up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5911
		 * picking the address of the loopback
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5912
		 * interface.  This is an undocumented feature.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5913
		 * However, we provide the same thing here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5914
		 * in order to have source and binary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5915
		 * compatibility with SunOS 4.x.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5916
		 * Update the T_CONN_REQ (sin/sin6) since it is used to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5917
		 * generate the T_CONN_CON.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5918
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5919
		dstaddr = htonl(INADDR_LOOPBACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5920
		*dstaddrp = dstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5921
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5922
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5923
	/* Handle __sin6_src_id if socket not bound to an IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5924
	if (srcid != 0 && tcp->tcp_ipha->ipha_src == INADDR_ANY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5925
		ip_srcid_find_id(srcid, &tcp->tcp_ip_src_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5926
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5927
		IN6_V4MAPPED_TO_IPADDR(&tcp->tcp_ip_src_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5928
		    tcp->tcp_ipha->ipha_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5929
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5931
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5932
	 * Don't let an endpoint connect to itself.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5933
	 * the test here does not catch the case where the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5934
	 * source IP addr was left unspecified by the user. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5935
	 * this case, the source addr is set in tcp_adapt_ire()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5936
	 * using the reply to the T_BIND message that we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5937
	 * down to IP here and the check is repeated in tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5938
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5939
	if (dstaddr == tcp->tcp_ipha->ipha_src &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5940
	    dstport == tcp->tcp_lport) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5941
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5942
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5943
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5945
	tcp->tcp_ipha->ipha_dst = dstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5946
	IN6_IPADDR_TO_V4MAPPED(dstaddr, &tcp->tcp_remote_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5947
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5948
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5949
	 * Massage a source route if any putting the first hop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5950
	 * in iph_dst. Compute a starting value for the checksum which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5951
	 * takes into account that the original iph_dst should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5952
	 * included in the checksum but that ip will include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5953
	 * first hop in the source route in the tcp checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5954
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5955
	tcp->tcp_sum = ip_massage_options(tcp->tcp_ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5956
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5957
	tcp->tcp_sum -= ((tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5958
	    (tcp->tcp_ipha->ipha_dst & 0xffff));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5959
	if ((int)tcp->tcp_sum < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5960
		tcp->tcp_sum--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5961
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5962
	tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5963
	    (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5964
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5965
	*(uint16_t *)tcph->th_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5966
	tcp->tcp_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5967
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5968
	oldstate = tcp->tcp_state;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5969
	/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5970
	 * At this point the remote destination address and remote port fields
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5971
	 * in the tcp-four-tuple have been filled in the tcp structure. Now we
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5972
	 * have to see which state tcp was in so we can take apropriate action.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5973
	 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5974
	if (oldstate == TCPS_IDLE) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5975
		/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5976
		 * We support a quick connect capability here, allowing
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5977
		 * clients to transition directly from IDLE to SYN_SENT
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5978
		 * tcp_bindi will pick an unused port, insert the connection
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5979
		 * in the bind hash and transition to BOUND state.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5980
		 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5981
		lport = tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5982
		lport = tcp_bindi(tcp, lport, &tcp->tcp_ip_src_v6, 0, B_TRUE,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5983
		    B_FALSE, B_FALSE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5984
		if (lport == 0) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5985
			mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5986
			goto failed;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5987
		}
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  5988
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5989
	tcp->tcp_state = TCPS_SYN_SENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5991
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5992
	 * TODO: allow data with connect requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5993
	 * by unlinking M_DATA trailers here and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5994
	 * linking them in behind the T_OK_ACK mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5995
	 * The tcp_rput() bind ack handler would then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5996
	 * feed them to tcp_wput_data() rather than call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5997
	 * tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5998
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  5999
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6000
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6001
		tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6002
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6003
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6004
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6005
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6006
		    sizeof (ipa_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6007
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6008
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6009
		    sizeof (ipa6_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6010
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6011
	if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6012
		/* Hang onto the T_OK_ACK for later. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6013
		linkb(mp1, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6014
		if (tcp->tcp_family == AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6015
			mp1 = ip_bind_v4(tcp->tcp_wq, mp1, tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6016
		else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6017
			mp1 = ip_bind_v6(tcp->tcp_wq, mp1, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6018
			    &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6020
		BUMP_MIB(&tcp_mib, tcpActiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6021
		tcp->tcp_active_open = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6022
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6023
		 * If the bind cannot complete immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6024
		 * IP will arrange to call tcp_rput_other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6025
		 * when the bind completes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6026
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6027
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6028
			tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6029
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6030
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6031
	/* Error case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6032
	tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6033
	mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6035
failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6036
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6037
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6038
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6039
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6040
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6041
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6042
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6043
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6044
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6045
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6046
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6048
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6049
 * Handle connect to IPv6 destinations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6050
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6051
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6052
tcp_connect_ipv6(tcp_t *tcp, mblk_t *mp, in6_addr_t *dstaddrp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6053
    in_port_t dstport, uint32_t flowinfo, uint_t srcid, uint32_t scope_id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6054
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6055
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6056
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6057
	ip6_rthdr_t *rth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6058
	int32_t  oldstate;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6059
	uint16_t lport;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6061
	ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6063
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6064
	 * If we're here, it means that the destination address is a native
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6065
	 * IPv6 address.  Return an error if tcp_ipversion is not IPv6.  A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6066
	 * reason why it might not be IPv6 is if the socket was bound to an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6067
	 * IPv4-mapped IPv6 address.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6068
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6069
	if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6070
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6071
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6072
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6074
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6075
	 * Interpret a zero destination to mean loopback.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6076
	 * Update the T_CONN_REQ (sin/sin6) since it is used to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6077
	 * generate the T_CONN_CON.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6078
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6079
	if (IN6_IS_ADDR_UNSPECIFIED(dstaddrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6080
		*dstaddrp = ipv6_loopback;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6081
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6083
	/* Handle __sin6_src_id if socket not bound to an IP address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6084
	if (srcid != 0 && IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6085
		ip_srcid_find_id(srcid, &tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6086
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6087
		tcp->tcp_ip_src_v6 = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6088
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6090
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6091
	 * Take care of the scope_id now and add ip6i_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6092
	 * if ip6i_t is not already allocated through TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6093
	 * sticky options. At this point tcp_ip6h does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6094
	 * have dst info, thus use dstaddrp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6095
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6096
	if (scope_id != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6097
	    IN6_IS_ADDR_LINKSCOPE(dstaddrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6098
		ip6_pkt_t *ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6099
		ip6i_t  *ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6101
		ipp->ipp_ifindex = scope_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6102
		ip6i = (ip6i_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6104
		if ((ipp->ipp_fields & IPPF_HAS_IP6I) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6105
		    ip6i != NULL && (ip6i->ip6i_nxt == IPPROTO_RAW)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6106
			/* Already allocated */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6107
			ip6i->ip6i_flags |= IP6I_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6108
			ip6i->ip6i_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6109
			ipp->ipp_fields |= IPPF_SCOPE_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6110
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6111
			int reterr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6112
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6113
			ipp->ipp_fields |= IPPF_SCOPE_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6114
			if (ipp->ipp_fields & IPPF_HAS_IP6I)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6115
				ip2dbg(("tcp_connect_v6: SCOPE_ID set\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6116
			reterr = tcp_build_hdrs(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6117
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6118
				goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6119
			ip1dbg(("tcp_connect_ipv6: tcp_bld_hdrs returned\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6120
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6121
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6123
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6124
	 * Don't let an endpoint connect to itself.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6125
	 * the test here does not catch the case where the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6126
	 * source IP addr was left unspecified by the user. In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6127
	 * this case, the source addr is set in tcp_adapt_ire()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6128
	 * using the reply to the T_BIND message that we send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6129
	 * down to IP here and the check is repeated in tcp_rput_other.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6130
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6131
	if (IN6_ARE_ADDR_EQUAL(dstaddrp, &tcp->tcp_ip6h->ip6_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6132
	    (dstport == tcp->tcp_lport)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6133
		mp = mi_tpi_err_ack_alloc(mp, TBADADDR, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6134
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6135
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6136
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6137
	tcp->tcp_ip6h->ip6_dst = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6138
	tcp->tcp_remote_v6 = *dstaddrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6139
	tcp->tcp_ip6h->ip6_vcf =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6140
	    (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6141
	    (flowinfo & ~IPV6_VERS_AND_FLOW_MASK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6144
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6145
	 * Massage a routing header (if present) putting the first hop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6146
	 * in ip6_dst. Compute a starting value for the checksum which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6147
	 * takes into account that the original ip6_dst should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6148
	 * included in the checksum but that ip will include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6149
	 * first hop in the source route in the tcp checksum.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6150
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6151
	rth = ip_find_rthdr_v6(tcp->tcp_ip6h, (uint8_t *)tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6152
	if (rth != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6154
		tcp->tcp_sum = ip_massage_options_v6(tcp->tcp_ip6h, rth);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6155
		tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6156
		    (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6157
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6158
		tcp->tcp_sum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6159
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6161
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6162
	*(uint16_t *)tcph->th_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6163
	tcp->tcp_fport = dstport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6165
	oldstate = tcp->tcp_state;
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6166
	/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6167
	 * At this point the remote destination address and remote port fields
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6168
	 * in the tcp-four-tuple have been filled in the tcp structure. Now we
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6169
	 * have to see which state tcp was in so we can take apropriate action.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6170
	 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6171
	if (oldstate == TCPS_IDLE) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6172
		/*
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6173
		 * We support a quick connect capability here, allowing
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6174
		 * clients to transition directly from IDLE to SYN_SENT
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6175
		 * tcp_bindi will pick an unused port, insert the connection
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6176
		 * in the bind hash and transition to BOUND state.
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6177
		 */
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6178
		lport = tcp_update_next_port(tcp_next_port_to_try, B_TRUE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6179
		lport = tcp_bindi(tcp, lport, &tcp->tcp_ip_src_v6, 0, B_TRUE,
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6180
		    B_FALSE, B_FALSE);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6181
		if (lport == 0) {
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6182
			mp = mi_tpi_err_ack_alloc(mp, TNOADDR, 0);
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6183
			goto failed;
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6184
		}
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
  6185
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6186
	tcp->tcp_state = TCPS_SYN_SENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6187
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6188
	 * TODO: allow data with connect requests
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6189
	 * by unlinking M_DATA trailers here and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6190
	 * linking them in behind the T_OK_ACK mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6191
	 * The tcp_rput() bind ack handler would then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6192
	 * feed them to tcp_wput_data() rather than call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6193
	 * tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6194
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6195
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6196
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6197
		tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6198
		goto failed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6199
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6200
	mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ, sizeof (ipa6_conn_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6201
	if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6202
		/* Hang onto the T_OK_ACK for later. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6203
		linkb(mp1, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6204
		mp1 = ip_bind_v6(tcp->tcp_wq, mp1, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6205
		    &tcp->tcp_sticky_ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6206
		BUMP_MIB(&tcp_mib, tcpActiveOpens);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6207
		tcp->tcp_active_open = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6208
		/* ip_bind_v6() may return ACK or ERROR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6209
		if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6210
			tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6211
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6213
	/* Error case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6214
	tcp->tcp_state = oldstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6215
	mp = mi_tpi_err_ack_alloc(mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6217
failed:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6218
	/* return error ack and blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6219
	if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6220
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6221
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6222
		tcp_err_ack_prim(tcp, NULL, T_CONN_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6223
		    TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6224
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6225
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6226
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6227
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6229
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6230
 * We need a stream q for detached closing tcp connections
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6231
 * to use.  Our client hereby indicates that this q is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6232
 * one to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6233
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6234
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6235
tcp_def_q_set(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6236
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6237
	struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6238
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6240
	mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6241
	iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6242
	mutex_enter(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6243
	if (tcp_g_q != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6244
		mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6245
		iocp->ioc_error = EALREADY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6246
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6247
		mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6249
		mp1 = tcp_ip_bind_mp(tcp, O_T_BIND_REQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6250
		if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6251
			mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6252
			iocp->ioc_error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6253
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6254
			tcp_g_q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6255
			mutex_exit(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6256
			iocp->ioc_error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6257
			iocp->ioc_rval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6258
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6259
			 * We are passing tcp_sticky_ipp as NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6260
			 * as it is not useful for tcp_default queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6261
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6262
			mp1 = ip_bind_v6(q, mp1, tcp->tcp_connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6263
			if (mp1 != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6264
				tcp_rput_other(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6265
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6266
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6267
	qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6268
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6270
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6271
 * Our client hereby directs us to reject the connection request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6272
 * that tcp_conn_request() marked with 'seqnum'.  Rejection consists
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6273
 * of sending the appropriate RST, not an ICMP error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6274
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6275
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6276
tcp_disconnect(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6277
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6278
	tcp_t	*ltcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6279
	t_scalar_t seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6280
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6282
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6283
	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_discon_req)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6284
		tcp_err_ack(tcp, mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6285
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6286
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6288
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6289
	 * Right now, upper modules pass down a T_DISCON_REQ to TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6290
	 * when the stream is in BOUND state. Do not send a reset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6291
	 * since the destination IP address is not valid, and it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6292
	 * be the initialized value of all zeros (broadcast address).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6293
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6294
	 * If TCP has sent down a bind request to IP and has not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6295
	 * received the reply, reject the request.  Otherwise, TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6296
	 * will be confused.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6297
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6298
	if (tcp->tcp_state <= TCPS_BOUND || tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6299
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  6300
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6301
			    "tcp_disconnect: bad state, %d", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6302
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6303
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6304
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6305
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6307
	seqnum = ((struct T_discon_req *)mp->b_rptr)->SEQ_number;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6309
	if (seqnum == -1 || tcp->tcp_conn_req_max == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6311
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6312
		 * According to TPI, for non-listeners, ignore seqnum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6313
		 * and disconnect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6314
		 * Following interpretation of -1 seqnum is historical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6315
		 * and implied TPI ? (TPI only states that for T_CONN_IND,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6316
		 * a valid seqnum should not be -1).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6317
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6318
		 *	-1 means disconnect everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6319
		 *	regardless even on a listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6320
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6321
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6322
		int old_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6324
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6325
		 * The connection can't be on the tcp_time_wait_head list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6326
		 * since it is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6327
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6328
		ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6329
		ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6330
		ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6331
		ltcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6332
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6333
		 * If it used to be a listener, check to make sure no one else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6334
		 * has taken the port before switching back to LISTEN state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6335
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6336
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6337
			connp = ipcl_lookup_listener_v4(tcp->tcp_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6338
			    tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6339
			    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6340
			if (connp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6341
				ltcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6342
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6343
			/* Allow tcp_bound_if listeners? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6344
			connp = ipcl_lookup_listener_v6(tcp->tcp_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6345
			    &tcp->tcp_ip6h->ip6_src, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6346
			    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6347
			if (connp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6348
				ltcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6349
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6350
		if (tcp->tcp_conn_req_max && ltcp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6351
			tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6352
		} else if (old_state > TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6353
			tcp->tcp_conn_req_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6354
			tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6355
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6356
		if (ltcp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6357
			CONN_DEC_REF(ltcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6358
		if (old_state == TCPS_SYN_SENT || old_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6359
			BUMP_MIB(&tcp_mib, tcpAttemptFails);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6360
		} else if (old_state == TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6361
		    old_state == TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6362
			BUMP_MIB(&tcp_mib, tcpEstabResets);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6363
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6365
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6366
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6368
		mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6369
		if ((tcp->tcp_conn_req_cnt_q0 != 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6370
		    (tcp->tcp_conn_req_cnt_q != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6371
			tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6372
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6373
		mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6375
		tcp_xmit_ctl("tcp_disconnect", tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6376
		    tcp->tcp_rnxt, TH_RST | TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6378
		tcp_reinit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6380
		if (old_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6381
			/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6382
			(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6383
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6384
		mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6385
		if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6386
			putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6387
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6388
	} else if (!tcp_eager_blowoff(tcp, seqnum)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6389
		tcp_err_ack(tcp, mp, TBADSEQ, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6390
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6391
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6392
	if (tcp->tcp_state >= TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6393
		/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6394
		(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6395
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6396
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6397
	if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6398
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6399
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6401
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6402
 * Diagnostic routine used to return a string associated with the tcp state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6403
 * Note that if the caller does not supply a buffer, it will use an internal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6404
 * static string.  This means that if multiple threads call this function at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6405
 * the same time, output can be corrupted...  Note also that this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6406
 * does not check the size of the supplied buffer.  The caller has to make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6407
 * sure that it is big enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6408
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6409
static char *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6410
tcp_display(tcp_t *tcp, char *sup_buf, char format)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6411
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6412
	char		buf1[30];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6413
	static char	priv_buf[INET6_ADDRSTRLEN * 2 + 80];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6414
	char		*buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6415
	char		*cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6416
	in6_addr_t	local, remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6417
	char		local_addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6418
	char		remote_addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6420
	if (sup_buf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6421
		buf = sup_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6422
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6423
		buf = priv_buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6425
	if (tcp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6426
		return ("NULL_TCP");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6427
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6428
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6429
		cp = "TCP_CLOSED";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6430
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6431
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6432
		cp = "TCP_IDLE";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6433
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6434
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6435
		cp = "TCP_BOUND";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6436
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6437
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6438
		cp = "TCP_LISTEN";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6439
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6440
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6441
		cp = "TCP_SYN_SENT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6442
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6443
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6444
		cp = "TCP_SYN_RCVD";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6445
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6446
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6447
		cp = "TCP_ESTABLISHED";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6448
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6449
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6450
		cp = "TCP_CLOSE_WAIT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6451
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6452
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6453
		cp = "TCP_FIN_WAIT_1";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6454
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6455
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6456
		cp = "TCP_CLOSING";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6457
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6458
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6459
		cp = "TCP_LAST_ACK";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6460
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6461
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6462
		cp = "TCP_FIN_WAIT_2";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6463
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6464
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6465
		cp = "TCP_TIME_WAIT";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6466
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6467
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6468
		(void) mi_sprintf(buf1, "TCPUnkState(%d)", tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6469
		cp = buf1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6470
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6471
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6472
	switch (format) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6473
	case DISP_ADDR_AND_PORT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6474
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6475
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6476
			 * Note that we use the remote address in the tcp_b
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6477
			 * structure.  This means that it will print out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6478
			 * the real destination address, not the next hop's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6479
			 * address if source routing is used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6480
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6481
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ip_src, &local);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6482
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_remote, &remote);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6484
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6485
			local = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6486
			remote = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6487
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6488
		(void) inet_ntop(AF_INET6, &local, local_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6489
		    sizeof (local_addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6490
		(void) inet_ntop(AF_INET6, &remote, remote_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6491
		    sizeof (remote_addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6492
		(void) mi_sprintf(buf, "[%s.%u, %s.%u] %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6493
		    local_addrbuf, ntohs(tcp->tcp_lport), remote_addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6494
		    ntohs(tcp->tcp_fport), cp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6495
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6496
	case DISP_PORT_ONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6497
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6498
		(void) mi_sprintf(buf, "[%u, %u] %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6499
		    ntohs(tcp->tcp_lport), ntohs(tcp->tcp_fport), cp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6500
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6501
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6502
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6503
	return (buf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6504
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6506
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6507
 * Called via squeue to get on to eager's perimeter to send a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6508
 * TH_RST. The listener wants the eager to disappear either
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6509
 * by means of tcp_eager_blowoff() or tcp_eager_cleanup()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6510
 * being called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6511
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6512
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6513
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6514
tcp_eager_kill(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6515
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6516
	conn_t	*econnp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6517
	tcp_t	*eager = econnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6518
	tcp_t	*listener = eager->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6520
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6521
	 * We could be called because listener is closing. Since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6522
	 * the eager is using listener's queue's, its not safe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6523
	 * Better use the default queue just to send the TH_RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6524
	 * out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6525
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6526
	eager->tcp_rq = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6527
	eager->tcp_wq = WR(tcp_g_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6528
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6529
	if (eager->tcp_state > TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6530
		tcp_xmit_ctl("tcp_eager_kill, can't wait",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6531
		    eager, eager->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6532
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6534
	/* We are here because listener wants this eager gone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6535
	if (listener != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6536
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6537
		tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6538
		if (eager->tcp_conn.tcp_eager_conn_ind == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6539
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6540
			 * The eager has sent a conn_ind up to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6541
			 * listener but listener decides to close
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6542
			 * instead. We need to drop the extra ref
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6543
			 * placed on eager in tcp_rput_data() before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6544
			 * sending the conn_ind to listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6545
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6546
			CONN_DEC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6547
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6548
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6549
		CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6550
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6552
	if (eager->tcp_state > TCPS_BOUND)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6553
		tcp_close_detached(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6554
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6556
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6557
 * Reset any eager connection hanging off this listener marked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6558
 * with 'seqnum' and then reclaim it's resources.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6559
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6560
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6561
tcp_eager_blowoff(tcp_t	*listener, t_scalar_t seqnum)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6562
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6563
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6564
	mblk_t 	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6565
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6566
	TCP_STAT(tcp_eager_blowoff_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6567
	eager = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6568
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6569
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6570
		eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6571
		if (eager == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6572
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6573
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6574
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6575
	} while (eager->tcp_conn_req_seqnum != seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6576
	CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6577
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6578
	mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6579
	squeue_fill(eager->tcp_connp->conn_sqp, mp, tcp_eager_kill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6580
	    eager->tcp_connp, SQTAG_TCP_EAGER_BLOWOFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6581
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6582
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6584
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6585
 * Reset any eager connection hanging off this listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6586
 * and then reclaim it's resources.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6587
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6588
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6589
tcp_eager_cleanup(tcp_t *listener, boolean_t q0_only)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6590
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6591
	tcp_t	*eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6592
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6593
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6594
	ASSERT(MUTEX_HELD(&listener->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6595
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6596
	if (!q0_only) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6597
		/* First cleanup q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6598
		TCP_STAT(tcp_eager_blowoff_q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6599
		eager = listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6600
		while (eager != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6601
			CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6602
			mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6603
			squeue_fill(eager->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6604
			    tcp_eager_kill, eager->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6605
			    SQTAG_TCP_EAGER_CLEANUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6606
			eager = eager->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6607
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6608
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6609
	/* Then cleanup q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6610
	TCP_STAT(tcp_eager_blowoff_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6611
	eager = listener->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6612
	while (eager != listener) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6613
		CONN_INC_REF(eager->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6614
		mp = &eager->tcp_closemp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6615
		squeue_fill(eager->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6616
		    tcp_eager_kill, eager->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6617
		    SQTAG_TCP_EAGER_CLEANUP_Q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6618
		eager = eager->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6620
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6622
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6623
 * If we are an eager connection hanging off a listener that hasn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6624
 * formally accepted the connection yet, get off his list and blow off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6625
 * any data that we have accumulated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6626
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6627
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6628
tcp_eager_unlink(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6629
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6630
	tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6632
	ASSERT(MUTEX_HELD(&listener->tcp_eager_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6633
	ASSERT(listener != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6634
	if (tcp->tcp_eager_next_q0 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6635
		ASSERT(tcp->tcp_eager_prev_q0 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6637
		/* Remove the eager tcp from q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6638
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6639
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6640
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6641
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6642
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6643
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6645
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6646
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6648
		if (tcp->tcp_syn_rcvd_timeout != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6649
			/* we have timed out before */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6650
			ASSERT(listener->tcp_syn_rcvd_timeout > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6651
			listener->tcp_syn_rcvd_timeout--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6652
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6653
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6654
		tcp_t   **tcpp = &listener->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6655
		tcp_t	*prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6656
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6657
		for (; tcpp[0]; tcpp = &tcpp[0]->tcp_eager_next_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6658
			if (tcpp[0] == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6659
				if (listener->tcp_eager_last_q == tcp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6660
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6661
					 * If we are unlinking the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6662
					 * element on the list, adjust
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6663
					 * tail pointer. Set tail pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6664
					 * to nil when list is empty.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6665
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6666
					ASSERT(tcp->tcp_eager_next_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6667
					if (listener->tcp_eager_last_q ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6668
					    listener->tcp_eager_next_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6669
						listener->tcp_eager_last_q =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6670
						NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6671
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6672
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6673
						 * We won't get here if there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6674
						 * is only one eager in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6675
						 * list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6676
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6677
						ASSERT(prev != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6678
						listener->tcp_eager_last_q =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6679
						    prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6680
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6681
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6682
				tcpp[0] = tcp->tcp_eager_next_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6683
				tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6684
				tcp->tcp_eager_last_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6685
				ASSERT(listener->tcp_conn_req_cnt_q > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6686
				listener->tcp_conn_req_cnt_q--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6687
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6688
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6689
			prev = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6690
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6691
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6692
	tcp->tcp_listener = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6693
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6695
/* Shorthand to generate and send TPI error acks to our client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6696
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6697
tcp_err_ack(tcp_t *tcp, mblk_t *mp, int t_error, int sys_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6698
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6699
	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6700
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6701
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6703
/* Shorthand to generate and send TPI error acks to our client */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6704
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6705
tcp_err_ack_prim(tcp_t *tcp, mblk_t *mp, int primitive,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6706
    int t_error, int sys_error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6707
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6708
	struct T_error_ack	*teackp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6710
	if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6711
	    M_PCPROTO, T_ERROR_ACK)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6712
		teackp = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6713
		teackp->ERROR_prim = primitive;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6714
		teackp->TLI_error = t_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6715
		teackp->UNIX_error = sys_error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6716
		putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6717
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6718
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6719
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6720
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6721
 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6722
 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6723
 * - the fact that the address of the array and its size never changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6724
 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6725
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6726
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6727
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6728
tcp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6729
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6730
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6732
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6733
		if (tcp_g_epriv_ports[i] != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6734
			(void) mi_mpprintf(mp, "%d ", tcp_g_epriv_ports[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6735
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6736
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6737
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6738
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6739
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6740
 * Hold a lock while changing tcp_g_epriv_ports to prevent multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6741
 * threads from changing it at the same time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6742
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6743
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6744
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6745
tcp_extra_priv_ports_add(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6746
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6747
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6748
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6749
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6751
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6752
	 * Fail the request if the new value does not lie within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6753
	 * port number limits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6754
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6755
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6756
	    new_value <= 0 || new_value >= 65536) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6757
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6758
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6759
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6760
	mutex_enter(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6761
	/* Check if the value is already in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6762
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6763
		if (new_value == tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6764
			mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6765
			return (EEXIST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6766
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6767
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6768
	/* Find an empty slot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6769
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6770
		if (tcp_g_epriv_ports[i] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6771
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6772
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6773
	if (i == tcp_g_num_epriv_ports) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6774
		mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6775
		return (EOVERFLOW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6776
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6777
	/* Set the new value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6778
	tcp_g_epriv_ports[i] = (uint16_t)new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6779
	mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6780
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6781
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6782
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6783
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6784
 * Hold a lock while changing tcp_g_epriv_ports to prevent multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6785
 * threads from changing it at the same time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6786
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6787
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6788
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6789
tcp_extra_priv_ports_del(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6790
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6791
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6792
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6793
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6795
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6796
	 * Fail the request if the new value does not lie within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6797
	 * port number limits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6798
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6799
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 || new_value <= 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6800
	    new_value >= 65536) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6801
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6802
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6804
	mutex_enter(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6805
	/* Check that the value is already in the list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6806
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6807
		if (tcp_g_epriv_ports[i] == new_value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6808
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6809
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6810
	if (i == tcp_g_num_epriv_ports) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6811
		mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6812
		return (ESRCH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6813
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6814
	/* Clear the value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6815
	tcp_g_epriv_ports[i] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6816
	mutex_exit(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6817
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6818
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6820
/* Return the TPI/TLI equivalent of our current tcp_state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6821
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6822
tcp_tpistate(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6823
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6824
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6825
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6826
		return (TS_UNBND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6827
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6828
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6829
		 * Return whether there are outstanding T_CONN_IND waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6830
		 * for the matching T_CONN_RES. Therefore don't count q0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6831
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6832
		if (tcp->tcp_conn_req_cnt_q > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6833
			return (TS_WRES_CIND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6834
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6835
			return (TS_IDLE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6836
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6837
		return (TS_IDLE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6838
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6839
		return (TS_WCON_CREQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6840
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6841
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6842
		 * Note: assumption: this has to the active open SYN_RCVD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6843
		 * The passive instance is detached in SYN_RCVD stage of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6844
		 * incoming connection processing so we cannot get request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6845
		 * for T_info_ack on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6846
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6847
		return (TS_WACK_CRES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6848
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6849
		return (TS_DATA_XFER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6850
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6851
		return (TS_WREQ_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6852
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6853
		return (TS_WIND_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6854
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6855
		return (TS_WIND_ORDREL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6857
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6858
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6859
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6860
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6861
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6862
		 * Following TS_WACK_DREQ7 is a rendition of "not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6863
		 * yet TS_IDLE" TPI state. There is no best match to any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6864
		 * TPI state for TCPS_{CLOSING, LAST_ACK, TIME_WAIT} but we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6865
		 * choose a value chosen that will map to TLI/XTI level
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6866
		 * state of TSTATECHNG (state is process of changing) which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6867
		 * captures what this dummy state represents.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6868
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6869
		return (TS_WACK_DREQ7);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6870
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6871
		cmn_err(CE_WARN, "tcp_tpistate: strange state (%d) %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6872
		    tcp->tcp_state, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6873
		    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6874
		return (TS_UNBND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6875
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6876
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6878
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6879
tcp_copy_info(struct T_info_ack *tia, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6880
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6881
	if (tcp->tcp_family == AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6882
		*tia = tcp_g_t_info_ack_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6883
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6884
		*tia = tcp_g_t_info_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6885
	tia->CURRENT_state = tcp_tpistate(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6886
	tia->OPT_size = tcp_max_optsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6887
	if (tcp->tcp_mss == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6888
		/* Not yet set - tcp_open does not set mss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6889
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6890
			tia->TIDU_size = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6891
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6892
			tia->TIDU_size = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6893
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6894
		tia->TIDU_size = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6895
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6896
	/* TODO: Default ETSDU is 1.  Is that correct for tcp? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6897
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6899
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6900
 * This routine responds to T_CAPABILITY_REQ messages.  It is called by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6901
 * tcp_wput.  Much of the T_CAPABILITY_ACK information is copied from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6902
 * tcp_g_t_info_ack.  The current state of the stream is copied from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6903
 * tcp_state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6904
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6905
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6906
tcp_capability_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6907
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6908
	t_uscalar_t		cap_bits1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6909
	struct T_capability_ack	*tcap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6911
	if (MBLKL(mp) < sizeof (struct T_capability_req)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6912
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6913
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6914
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6915
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6916
	cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6918
	mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6919
	    mp->b_datap->db_type, T_CAPABILITY_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6920
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6921
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6922
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6923
	tcap = (struct T_capability_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6924
	tcap->CAP_bits1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6926
	if (cap_bits1 & TC1_INFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6927
		tcp_copy_info(&tcap->INFO_ack, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6928
		tcap->CAP_bits1 |= TC1_INFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6929
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6931
	if (cap_bits1 & TC1_ACCEPTOR_ID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6932
		tcap->ACCEPTOR_id = tcp->tcp_acceptor_id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6933
		tcap->CAP_bits1 |= TC1_ACCEPTOR_ID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6934
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6936
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6937
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6939
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6940
 * This routine responds to T_INFO_REQ messages.  It is called by tcp_wput.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6941
 * Most of the T_INFO_ACK information is copied from tcp_g_t_info_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6942
 * The current state of the stream is copied from tcp_state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6943
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6944
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6945
tcp_info_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6946
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6947
	mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6948
	    T_INFO_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6949
	if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6950
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6951
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6952
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6953
	tcp_copy_info((struct T_info_ack *)mp->b_rptr, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6954
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6955
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6957
/* Respond to the TPI addr request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6958
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6959
tcp_addr_req(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6960
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6961
	sin_t	*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6962
	mblk_t	*ackmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6963
	struct T_addr_ack *taa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6965
	/* Make it large enough for worst case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6966
	ackmp = reallocb(mp, sizeof (struct T_addr_ack) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6967
	    2 * sizeof (sin6_t), 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6968
	if (ackmp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6969
		tcp_err_ack(tcp, mp, TSYSERR, ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6970
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6971
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6973
	if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6974
		tcp_addr_req_ipv6(tcp, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6975
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6976
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6977
	taa = (struct T_addr_ack *)ackmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6978
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6979
	bzero(taa, sizeof (struct T_addr_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6980
	ackmp->b_wptr = (uchar_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6982
	taa->PRIM_type = T_ADDR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6983
	ackmp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6985
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6986
	 * Note: Following code assumes 32 bit alignment of basic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6987
	 * data structures like sin_t and struct T_addr_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6988
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6989
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6990
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6991
		 * Fill in local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6992
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6993
		taa->LOCADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6994
		taa->LOCADDR_offset = sizeof (*taa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6995
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6996
		sin = (sin_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6998
		/* Fill zeroes and then intialize non-zero fields */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  6999
		*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7000
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7001
		sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7002
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7003
		sin->sin_addr.s_addr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7004
		sin->sin_port = *(uint16_t *)tcp->tcp_tcph->th_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7006
		ackmp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7007
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7008
		if (tcp->tcp_state >= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7009
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7010
			 * Fill in Remote address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7011
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7012
			taa->REMADDR_length = sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7013
			taa->REMADDR_offset = ROUNDUP32(taa->LOCADDR_offset +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7014
						taa->LOCADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7016
			sin = (sin_t *)(ackmp->b_rptr + taa->REMADDR_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7017
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7018
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7019
			sin->sin_addr.s_addr = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7020
			sin->sin_port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7021
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7022
			ackmp->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7023
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7024
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7025
	putnext(tcp->tcp_rq, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7026
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7027
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7028
/* Assumes that tcp_addr_req gets enough space and alignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7029
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7030
tcp_addr_req_ipv6(tcp_t *tcp, mblk_t *ackmp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7031
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7032
	sin6_t	*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7033
	struct T_addr_ack *taa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7035
	ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7036
	ASSERT(OK_32PTR(ackmp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7037
	ASSERT(ackmp->b_wptr - ackmp->b_rptr >= sizeof (struct T_addr_ack) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7038
	    2 * sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7039
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7040
	taa = (struct T_addr_ack *)ackmp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7042
	bzero(taa, sizeof (struct T_addr_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7043
	ackmp->b_wptr = (uchar_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7045
	taa->PRIM_type = T_ADDR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7046
	ackmp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7048
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7049
	 * Note: Following code assumes 32 bit alignment of basic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7050
	 * data structures like sin6_t and struct T_addr_ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7051
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7052
	if (tcp->tcp_state >= TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7053
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7054
		 * Fill in local address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7055
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7056
		taa->LOCADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7057
		taa->LOCADDR_offset = sizeof (*taa);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7059
		sin6 = (sin6_t *)&taa[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7060
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7062
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7063
		sin6->sin6_addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7064
		sin6->sin6_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7066
		ackmp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7068
		if (tcp->tcp_state >= TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7069
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7070
			 * Fill in Remote address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7071
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7072
			taa->REMADDR_length = sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7073
			taa->REMADDR_offset = ROUNDUP32(taa->LOCADDR_offset +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7074
						taa->LOCADDR_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7075
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7076
			sin6 = (sin6_t *)(ackmp->b_rptr + taa->REMADDR_offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7077
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7078
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7079
			sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7080
			    tcp->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7081
			    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7082
			sin6->sin6_addr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7083
			sin6->sin6_port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7085
			ackmp->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7086
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7087
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7088
	putnext(tcp->tcp_rq, ackmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7089
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7091
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7092
 * Handle reinitialization of a tcp structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7093
 * Maintain "binding state" resetting the state to BOUND, LISTEN, or IDLE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7094
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7095
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7096
tcp_reinit(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7097
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7098
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7099
	int 	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7101
	TCP_STAT(tcp_reinit_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7103
	/* tcp_reinit should never be called for detached tcp_t's */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7104
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7105
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7106
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7107
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7108
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7109
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7111
	/* Cancel outstanding timers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7112
	tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7114
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7115
	 * Reset everything in the state vector, after updating global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7116
	 * MIB data from instance counters.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7117
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7118
	UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7119
	tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7120
	UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7121
	tcp->tcp_obsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7123
	tcp_close_mpp(&tcp->tcp_xmit_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7124
	if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7125
		tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7126
	tcp->tcp_xmit_last = tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7127
	tcp->tcp_unsent = tcp->tcp_xmit_tail_unsent = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7128
	if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7129
	    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7130
		tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7131
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7132
	tcp_close_mpp(&tcp->tcp_reass_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7133
	tcp->tcp_reass_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7134
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7135
		/* Free b_next chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7136
		tcp_close_mpp(&tcp->tcp_rcv_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7137
		tcp->tcp_rcv_last_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7138
		tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7139
		tcp->tcp_rcv_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7140
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7141
	tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7143
	if ((mp = tcp->tcp_urp_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7144
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7145
		tcp->tcp_urp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7146
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7147
	if ((mp = tcp->tcp_urp_mark_mp) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7148
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7149
		tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7150
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7151
	if (tcp->tcp_fused_sigurg_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7152
		freeb(tcp->tcp_fused_sigurg_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7153
		tcp->tcp_fused_sigurg_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7156
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7157
	 * Following is a union with two members which are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7158
	 * identical types and size so the following cleanup
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7159
	 * is enough.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7160
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7161
	tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7163
	CL_INET_DISCONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7165
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7166
	 * The connection can't be on the tcp_time_wait_head list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7167
	 * since it is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7168
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7169
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7170
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7171
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7173
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7174
	 * Reset/preserve other values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7175
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7176
	tcp_reinit_values(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7177
	ipcl_hash_remove(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7178
	conn_delete_ire(tcp->tcp_connp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7180
	if (tcp->tcp_conn_req_max != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7181
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7182
		 * This is the case when a TLI program uses the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7183
		 * transport end point to accept a connection.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7184
		 * makes the TCP both a listener and acceptor.  When
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7185
		 * this connection is closed, we need to set the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7186
		 * back to TCPS_LISTEN.  Make sure that the eager list
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7187
		 * is reinitialized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7188
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7189
		 * Note that this stream is still bound to the four
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7190
		 * tuples of the previous connection in IP.  If a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7191
		 * SYN with different foreign address comes in, IP will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7192
		 * not find it and will send it to the global queue.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7193
		 * the global queue, TCP will do a tcp_lookup_listener()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7194
		 * to find this stream.  This works because this stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7195
		 * is only removed from connected hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7196
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7197
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7198
		tcp->tcp_state = TCPS_LISTEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7199
		tcp->tcp_eager_next_q0 = tcp->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7200
		tcp->tcp_connp->conn_recv = tcp_conn_request;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7201
		if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7202
			ASSERT(tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7203
			(void) ipcl_bind_insert_v6(tcp->tcp_connp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7204
			    &tcp->tcp_ip6h->ip6_src, tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7205
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7206
			ASSERT(!tcp->tcp_connp->conn_af_isv6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7207
			(void) ipcl_bind_insert(tcp->tcp_connp, IPPROTO_TCP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7208
			    tcp->tcp_ipha->ipha_src, tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7209
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7210
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7211
		tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7214
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7215
	 * Initialize to default values
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7216
	 * Can't fail since enough header template space already allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7217
	 * at open().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7218
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7219
	err = tcp_init_values(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7220
	ASSERT(err == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7221
	/* Restore state in tcp_tcph */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7222
	bcopy(&tcp->tcp_lport, tcp->tcp_tcph->th_lport, TCP_PORT_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7223
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7224
		tcp->tcp_ipha->ipha_src = tcp->tcp_bound_source;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7225
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7226
		tcp->tcp_ip6h->ip6_src = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7227
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7228
	 * Copy of the src addr. in tcp_t is needed in tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7229
	 * since the lookup funcs can only lookup on tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7230
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7231
	tcp->tcp_ip_src_v6 = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7233
	ASSERT(tcp->tcp_ptpbhn != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7234
	tcp->tcp_rq->q_hiwat = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7235
	tcp->tcp_rwnd = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7236
	tcp->tcp_mss = tcp->tcp_ipversion != IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7237
	    tcp_mss_def_ipv6 : tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7238
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7239
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7240
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7241
 * Force values to zero that need be zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7242
 * Do not touch values asociated with the BOUND or LISTEN state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7243
 * since the connection will end up in that state after the reinit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7244
 * NOTE: tcp_reinit_values MUST have a line for each field in the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7245
 * structure!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7246
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7247
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7248
tcp_reinit_values(tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7249
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7250
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7251
#ifndef	lint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7252
#define	DONTCARE(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7253
#define	PRESERVE(x)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7254
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7255
#define	DONTCARE(x)	((x) = (x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7256
#define	PRESERVE(x)	((x) = (x))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7257
#endif	/* lint */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7259
	PRESERVE(tcp->tcp_bind_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7260
	PRESERVE(tcp->tcp_ptpbhn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7261
	PRESERVE(tcp->tcp_acceptor_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7262
	PRESERVE(tcp->tcp_ptpahn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7264
	/* Should be ASSERT NULL on these with new code! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7265
	ASSERT(tcp->tcp_time_wait_next == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7266
	ASSERT(tcp->tcp_time_wait_prev == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7267
	ASSERT(tcp->tcp_time_wait_expire == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7268
	PRESERVE(tcp->tcp_state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7269
	PRESERVE(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7270
	PRESERVE(tcp->tcp_wq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7272
	ASSERT(tcp->tcp_xmit_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7273
	ASSERT(tcp->tcp_xmit_last == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7274
	ASSERT(tcp->tcp_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7275
	ASSERT(tcp->tcp_xmit_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7276
	ASSERT(tcp->tcp_xmit_tail_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7277
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7278
	tcp->tcp_snxt = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7279
	tcp->tcp_suna = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7280
	tcp->tcp_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7281
	DONTCARE(tcp->tcp_cwnd);		/* Init in tcp_mss_set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7283
	ASSERT(tcp->tcp_ibsegs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7284
	ASSERT(tcp->tcp_obsegs == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7286
	if (tcp->tcp_iphc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7287
		ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7288
		bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7289
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7291
	DONTCARE(tcp->tcp_naglim);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7292
	DONTCARE(tcp->tcp_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7293
	DONTCARE(tcp->tcp_ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7294
	DONTCARE(tcp->tcp_ip6h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7295
	DONTCARE(tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7296
	DONTCARE(tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7297
	DONTCARE(tcp->tcp_tcp_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7298
	tcp->tcp_valid_bits = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7300
	DONTCARE(tcp->tcp_xmit_hiwater);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7301
	DONTCARE(tcp->tcp_timer_backoff);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7302
	DONTCARE(tcp->tcp_last_recv_time);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7303
	tcp->tcp_last_rcv_lbolt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7305
	tcp->tcp_init_cwnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7307
	tcp->tcp_urp_last_valid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7308
	tcp->tcp_hard_binding = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7309
	tcp->tcp_hard_bound = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7310
	PRESERVE(tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7311
	PRESERVE(tcp->tcp_cpid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7312
	PRESERVE(tcp->tcp_exclbind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7314
	tcp->tcp_fin_acked = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7315
	tcp->tcp_fin_rcvd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7316
	tcp->tcp_fin_sent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7317
	tcp->tcp_ordrel_done = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7319
	tcp->tcp_debug = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7320
	tcp->tcp_dontroute = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7321
	tcp->tcp_broadcast = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7323
	tcp->tcp_useloopback = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7324
	tcp->tcp_reuseaddr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7325
	tcp->tcp_oobinline = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7326
	tcp->tcp_dgram_errind = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7328
	tcp->tcp_detached = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7329
	tcp->tcp_bind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7330
	tcp->tcp_unbind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7331
	tcp->tcp_deferred_clean_death = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7333
	tcp->tcp_snd_ws_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7334
	tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7335
	tcp->tcp_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7336
	tcp->tcp_ka_enabled = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7337
	tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7339
	tcp->tcp_loopback = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7340
	tcp->tcp_localnet = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7341
	tcp->tcp_syn_defense = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7342
	tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7344
	tcp->tcp_active_open = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7345
	ASSERT(tcp->tcp_timeout == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7346
	tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7347
	tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7349
	tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7350
	PRESERVE(tcp->tcp_recvdstaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7351
	tcp->tcp_hwcksum = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7353
	tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7354
	DONTCARE(tcp->tcp_maxpsz);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7356
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7357
	tcp->tcp_mdt_hdr_head = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7358
	tcp->tcp_mdt_hdr_tail = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7360
	tcp->tcp_conn_def_q0 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7361
	tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7362
	tcp->tcp_anon_priv_bind = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7363
	tcp->tcp_ecn_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7364
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7365
	tcp->tcp_cwr = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7366
	tcp->tcp_ecn_echo_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7368
	if (tcp->tcp_sack_info != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7369
		if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7370
			TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7371
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7372
		kmem_cache_free(tcp_sack_info_cache, tcp->tcp_sack_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7373
		tcp->tcp_sack_info = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7374
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7376
	tcp->tcp_rcv_ws = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7377
	tcp->tcp_snd_ws = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7378
	tcp->tcp_ts_recent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7379
	tcp->tcp_rnxt = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7380
	DONTCARE(tcp->tcp_rwnd);		/* Set in tcp_reinit() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7381
	tcp->tcp_if_mtu = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7383
	ASSERT(tcp->tcp_reass_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7384
	ASSERT(tcp->tcp_reass_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7386
	tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7388
	ASSERT(tcp->tcp_rcv_list == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7389
	ASSERT(tcp->tcp_rcv_last_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7390
	ASSERT(tcp->tcp_rcv_last_tail == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7391
	ASSERT(tcp->tcp_rcv_cnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7393
	DONTCARE(tcp->tcp_cwnd_ssthresh);	/* Init in tcp_adapt_ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7394
	DONTCARE(tcp->tcp_cwnd_max);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7395
	tcp->tcp_csuna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7396
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7397
	tcp->tcp_rto = 0;			/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7398
	DONTCARE(tcp->tcp_rtt_sa);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7399
	DONTCARE(tcp->tcp_rtt_sd);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7400
	tcp->tcp_rtt_update = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7402
	DONTCARE(tcp->tcp_swl1); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7403
	DONTCARE(tcp->tcp_swl2); /* Init in case TCPS_LISTEN/TCPS_SYN_SENT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7405
	tcp->tcp_rack = 0;			/* Displayed in mib */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7406
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7407
	tcp->tcp_rack_cur_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7408
	tcp->tcp_rack_abs_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7410
	tcp->tcp_max_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7411
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7412
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7414
	DONTCARE(tcp->tcp_xmit_lowater);	/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7416
	DONTCARE(tcp->tcp_irs);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7417
	DONTCARE(tcp->tcp_iss);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7418
	DONTCARE(tcp->tcp_fss);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7419
	DONTCARE(tcp->tcp_urg);			/* tcp_valid_bits cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7420
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7421
	ASSERT(tcp->tcp_conn_req_cnt_q == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7422
	ASSERT(tcp->tcp_conn_req_cnt_q0 == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7423
	PRESERVE(tcp->tcp_conn_req_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7424
	PRESERVE(tcp->tcp_conn_req_seqnum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7426
	DONTCARE(tcp->tcp_ip_hdr_len);		/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7427
	DONTCARE(tcp->tcp_first_timer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7428
	DONTCARE(tcp->tcp_second_timer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7429
	DONTCARE(tcp->tcp_first_ctimer_threshold); /* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7430
	DONTCARE(tcp->tcp_second_ctimer_threshold); /* in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7432
	tcp->tcp_lingertime = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7434
	DONTCARE(tcp->tcp_urp_last);	/* tcp_urp_last_valid is cleared */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7435
	ASSERT(tcp->tcp_urp_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7436
	ASSERT(tcp->tcp_urp_mark_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7437
	ASSERT(tcp->tcp_fused_sigurg_mp == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7439
	ASSERT(tcp->tcp_eager_next_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7440
	ASSERT(tcp->tcp_eager_last_q == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7441
	ASSERT((tcp->tcp_eager_next_q0 == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7442
	    tcp->tcp_eager_prev_q0 == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7443
	    tcp->tcp_eager_next_q0 == tcp->tcp_eager_prev_q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7444
	ASSERT(tcp->tcp_conn.tcp_eager_conn_ind == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7446
	tcp->tcp_client_errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7448
	DONTCARE(tcp->tcp_sum);			/* Init in tcp_init_values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7450
	tcp->tcp_remote_v6 = ipv6_all_zeros;	/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7452
	PRESERVE(tcp->tcp_bound_source_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7453
	tcp->tcp_last_sent_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7454
	tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7456
	tcp->tcp_fport = 0;			/* Displayed in MIB */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7457
	PRESERVE(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7459
	PRESERVE(tcp->tcp_acceptor_lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7461
	ASSERT(tcp->tcp_ordrelid == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7462
	PRESERVE(tcp->tcp_acceptor_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7463
	DONTCARE(tcp->tcp_ipsec_overhead);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7465
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7466
	 * If tcp_tracing flag is ON (i.e. We have a trace buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7467
	 * in tcp structure and now tracing), Re-initialize all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7468
	 * members of tcp_traceinfo.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7469
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7470
	if (tcp->tcp_tracebuf != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7471
		bzero(tcp->tcp_tracebuf, sizeof (tcptrch_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7472
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7474
	PRESERVE(tcp->tcp_family);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7475
	if (tcp->tcp_family == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7476
		tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7477
		tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7478
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7479
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7480
		tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7481
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7483
	tcp->tcp_bound_if = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7484
	tcp->tcp_ipv6_recvancillary = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7485
	tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7486
	tcp->tcp_recvhops = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7487
	tcp->tcp_closed = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7488
	tcp->tcp_cleandeathtag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7489
	if (tcp->tcp_hopopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7490
		mi_free(tcp->tcp_hopopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7491
		tcp->tcp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7492
		tcp->tcp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7493
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7494
	ASSERT(tcp->tcp_hopoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7495
	if (tcp->tcp_dstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7496
		mi_free(tcp->tcp_dstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7497
		tcp->tcp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7498
		tcp->tcp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7499
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7500
	ASSERT(tcp->tcp_dstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7501
	if (tcp->tcp_rtdstopts != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7502
		mi_free(tcp->tcp_rtdstopts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7503
		tcp->tcp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7504
		tcp->tcp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7505
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7506
	ASSERT(tcp->tcp_rtdstoptslen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7507
	if (tcp->tcp_rthdr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7508
		mi_free(tcp->tcp_rthdr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7509
		tcp->tcp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7510
		tcp->tcp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7511
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7512
	ASSERT(tcp->tcp_rthdrlen == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7513
	PRESERVE(tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7514
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7515
	/* Reset fusion-related fields */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7516
	tcp->tcp_fused = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7517
	tcp->tcp_unfusable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7518
	tcp->tcp_fused_sigurg = B_FALSE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7519
	tcp->tcp_direct_sockfs = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7520
	tcp->tcp_fuse_syncstr_stopped = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7521
	tcp->tcp_loopback_peer = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7522
	tcp->tcp_fuse_rcv_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7523
	tcp->tcp_fuse_rcv_unread_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7524
	tcp->tcp_fuse_rcv_unread_cnt = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7526
	tcp->tcp_in_ack_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7527
	tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7528
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7529
	PRESERVE(tcp->tcp_squeue_bytes);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7530
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7531
#undef	DONTCARE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7532
#undef	PRESERVE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7533
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7535
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7536
 * Allocate necessary resources and initialize state vector.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7537
 * Guaranteed not to fail so that when an error is returned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7538
 * the caller doesn't need to do any additional cleanup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7539
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7540
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7541
tcp_init(tcp_t *tcp, queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7542
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7543
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7545
	tcp->tcp_rq = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7546
	tcp->tcp_wq = WR(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7547
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7548
	if ((err = tcp_init_values(tcp)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7549
		tcp_timers_stop(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7550
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7551
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7553
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7554
tcp_init_values(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7555
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7556
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7558
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7559
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7560
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7561
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7562
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7564
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7565
	 * Initialize tcp_rtt_sa and tcp_rtt_sd so that the calculated RTO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7566
	 * will be close to tcp_rexmit_interval_initial.  By doing this, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7567
	 * allow the algorithm to adjust slowly to large fluctuations of RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7568
	 * during first few transmissions of a connection as seen in slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7569
	 * links.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7570
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7571
	tcp->tcp_rtt_sa = tcp_rexmit_interval_initial << 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7572
	tcp->tcp_rtt_sd = tcp_rexmit_interval_initial >> 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7573
	tcp->tcp_rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7574
	    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7575
	    tcp_conn_grace_period;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7576
	if (tcp->tcp_rto < tcp_rexmit_interval_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7577
		tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7578
	tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7579
	tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7580
	tcp->tcp_last_recv_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7581
	tcp->tcp_cwnd_max = tcp_cwnd_max_;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7582
	tcp->tcp_snd_burst = TCP_CWND_INFINITE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7584
	tcp->tcp_maxpsz = tcp_maxpsz_multiplier;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7586
	tcp->tcp_first_timer_threshold = tcp_ip_notify_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7587
	tcp->tcp_first_ctimer_threshold = tcp_ip_notify_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7588
	tcp->tcp_second_timer_threshold = tcp_ip_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7589
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7590
	 * Fix it to tcp_ip_abort_linterval later if it turns out to be a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7591
	 * passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7592
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7593
	tcp->tcp_second_ctimer_threshold = tcp_ip_abort_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7595
	tcp->tcp_naglim = tcp_naglim_def;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7597
	/* NOTE:  ISS is now set in tcp_adapt_ire(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7599
	tcp->tcp_mdt_hdr_head = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7600
	tcp->tcp_mdt_hdr_tail = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7601
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7602
	/* Reset fusion-related fields */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7603
	tcp->tcp_fused = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7604
	tcp->tcp_unfusable = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7605
	tcp->tcp_fused_sigurg = B_FALSE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7606
	tcp->tcp_direct_sockfs = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7607
	tcp->tcp_fuse_syncstr_stopped = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7608
	tcp->tcp_loopback_peer = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7609
	tcp->tcp_fuse_rcv_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7610
	tcp->tcp_fuse_rcv_unread_hiwater = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  7611
	tcp->tcp_fuse_rcv_unread_cnt = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7612
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7613
	/* Initialize the header template */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7614
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7615
		err = tcp_header_init_ipv4(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7616
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7617
		err = tcp_header_init_ipv6(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7618
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7619
	if (err)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7620
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7622
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7623
	 * Init the window scale to the max so tcp_rwnd_set() won't pare
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7624
	 * down tcp_rwnd. tcp_adapt_ire() will set the right value later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7625
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7626
	tcp->tcp_rcv_ws = TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7627
	tcp->tcp_xmit_lowater = tcp_xmit_lowat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7628
	tcp->tcp_xmit_hiwater = tcp_xmit_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7630
	tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7631
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7632
	 * Init the tcp_debug option.  This value determines whether TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7633
	 * calls strlog() to print out debug messages.  Doing this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7634
	 * initialization here means that this value is not inherited thru
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7635
	 * tcp_reinit().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7636
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7637
	tcp->tcp_debug = tcp_dbg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7639
	tcp->tcp_ka_interval = tcp_keepalive_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7640
	tcp->tcp_ka_abort_thres = tcp_keepalive_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7642
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7643
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7645
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7646
 * Initialize the IPv4 header. Loses any record of any IP options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7647
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7648
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7649
tcp_header_init_ipv4(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7650
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7651
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7652
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7654
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7655
	 * This is a simple initialization. If there's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7656
	 * already a template, it should never be too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7657
	 * so reuse it.  Otherwise, allocate space for the new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7658
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7659
	if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7660
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7661
		tcp->tcp_iphc_len = TCP_MAX_COMBINED_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7662
		tcp->tcp_iphc = kmem_cache_alloc(tcp_iphc_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7663
		if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7664
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7665
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7666
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7667
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7668
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7669
	tcp->tcp_ipha = (ipha_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7670
	tcp->tcp_ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7671
	tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7672
	tcp->tcp_hdr_len = sizeof (ipha_t) + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7673
	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7674
	tcp->tcp_ip_hdr_len = sizeof (ipha_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7675
	tcp->tcp_ipha->ipha_length = htons(sizeof (ipha_t) + sizeof (tcph_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7676
	tcp->tcp_ipha->ipha_version_and_hdr_length
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7677
		= (IP_VERSION << 4) | IP_SIMPLE_HDR_LENGTH_IN_WORDS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7678
	tcp->tcp_ipha->ipha_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7679
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7680
	tcp->tcp_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7681
	tcp->tcp_tos = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7682
	tcp->tcp_ipha->ipha_fragment_offset_and_flags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7683
	tcp->tcp_ipha->ipha_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7684
	tcp->tcp_ipha->ipha_protocol = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7686
	tcph = (tcph_t *)(tcp->tcp_iphc + sizeof (ipha_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7687
	tcp->tcp_tcph = tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7688
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7689
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7690
	 * IP wants our header length in the checksum field to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7691
	 * allow it to perform a single pseudo-header+checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7692
	 * calculation on behalf of TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7693
	 * Include the adjustment for a source route once IP_OPTIONS is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7694
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7695
	sum = sizeof (tcph_t) + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7696
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7697
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7698
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7699
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7701
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7702
 * Initialize the IPv6 header. Loses any record of any IPv6 extension headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7703
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7704
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7705
tcp_header_init_ipv6(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7706
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7707
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7708
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7709
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7710
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7711
	 * This is a simple initialization. If there's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7712
	 * already a template, it should never be too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7713
	 * so reuse it. Otherwise, allocate space for the new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7714
	 * Ensure that there is enough space to "downgrade" the tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7715
	 * to an IPv4 tcp_t. This requires having space for a full load
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7716
	 * of IPv4 options, as well as a full load of TCP options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7717
	 * (TCP_MAX_COMBINED_HEADER_LENGTH, 120 bytes); this is more space
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7718
	 * than a v6 header and a TCP header with a full load of TCP options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7719
	 * (IPV6_HDR_LEN is 40 bytes; TCP_MAX_HDR_LENGTH is 60 bytes).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7720
	 * We want to avoid reallocation in the "downgraded" case when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7721
	 * processing outbound IPv4 options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7722
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7723
	if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7724
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7725
		tcp->tcp_iphc_len = TCP_MAX_COMBINED_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7726
		tcp->tcp_iphc = kmem_cache_alloc(tcp_iphc_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7727
		if (tcp->tcp_iphc == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7728
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7729
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7730
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7731
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7732
	ASSERT(tcp->tcp_iphc_len >= TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7733
	tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7734
	tcp->tcp_hdr_len = IPV6_HDR_LEN + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7735
	tcp->tcp_tcp_hdr_len = sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7736
	tcp->tcp_ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7737
	tcp->tcp_ip6h = (ip6_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7738
	tcp->tcp_ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7740
	/* Initialize the header template */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7742
	tcp->tcp_ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7743
	tcp->tcp_ip6h->ip6_plen = ntohs(sizeof (tcph_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7744
	tcp->tcp_ip6h->ip6_nxt = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7745
	tcp->tcp_ip6h->ip6_hops = (uint8_t)tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7747
	tcph = (tcph_t *)(tcp->tcp_iphc + IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7748
	tcp->tcp_tcph = tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7749
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7750
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7751
	 * IP wants our header length in the checksum field to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7752
	 * allow it to perform a single psuedo-header+checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7753
	 * calculation on behalf of TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7754
	 * Include the adjustment for a source route when IPV6_RTHDR is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7755
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7756
	sum = sizeof (tcph_t) + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7757
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7758
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7759
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7762
/* At minimum we need 4 bytes in the TCP header for the lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7763
#define	ICMP_MIN_TCP_HDR	4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7765
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7766
 * tcp_icmp_error is called by tcp_rput_other to process ICMP error messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7767
 * passed up by IP. The message is always received on the correct tcp_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7768
 * Assumes that IP has pulled up everything up to and including the ICMP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7769
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7770
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7771
tcp_icmp_error(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7772
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7773
	icmph_t *icmph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7774
	ipha_t	*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7775
	int	iph_hdr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7776
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7777
	boolean_t ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7778
	boolean_t secure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7779
	mblk_t *first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7780
	uint32_t new_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7781
	uint32_t ratio;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7782
	size_t mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7783
	uint32_t seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7784
	uint32_t seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7786
	/* Assume IP provides aligned packets - otherwise toss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7787
	if (!OK_32PTR(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7788
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7789
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7790
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7791
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7792
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7793
	 * Since ICMP errors are normal data marked with M_CTL when sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7794
	 * to TCP or UDP, we have to look for a IPSEC_IN value to identify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7795
	 * packets starting with an ipsec_info_t, see ipsec_info.h.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7796
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7797
	if ((mp_size == sizeof (ipsec_info_t)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7798
	    (((ipsec_info_t *)mp->b_rptr)->ipsec_info_type == IPSEC_IN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7799
		ASSERT(mp->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7800
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7801
		/* IP should have done this */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7802
		ASSERT(OK_32PTR(mp->b_rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7803
		mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7804
		ipsec_mctl = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7805
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7807
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7808
	 * Verify that we have a complete outer IP header. If not, drop it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7809
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7810
	if (mp_size < sizeof (ipha_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7811
noticmpv4:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7812
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7813
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7816
	ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7817
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7818
	 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7819
	 * upstream. ICMPv6 is handled in tcp_icmp_error_ipv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7820
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7821
	switch (IPH_HDR_VERSION(ipha)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7822
	case IPV6_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7823
		tcp_icmp_error_ipv6(tcp, first_mp, ipsec_mctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7824
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7825
	case IPV4_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7826
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7827
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7828
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7831
	/* Skip past the outer IP and ICMP headers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7832
	iph_hdr_length = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7833
	icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7834
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7835
	 * If we don't have the correct outer IP header length or if the ULP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7836
	 * is not IPPROTO_ICMP or if we don't have a complete inner IP header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7837
	 * send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7838
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7839
	if (iph_hdr_length < sizeof (ipha_t) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7840
	    ipha->ipha_protocol != IPPROTO_ICMP ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7841
	    (ipha_t *)&icmph[1] + 1 > (ipha_t *)mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7842
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7843
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7844
	ipha = (ipha_t *)&icmph[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7846
	/* Skip past the inner IP and find the ULP header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7847
	iph_hdr_length = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7848
	tcph = (tcph_t *)((char *)ipha + iph_hdr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7849
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7850
	 * If we don't have the correct inner IP header length or if the ULP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7851
	 * is not IPPROTO_TCP or if we don't have at least ICMP_MIN_TCP_HDR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7852
	 * bytes of TCP header, drop it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7853
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7854
	if (iph_hdr_length < sizeof (ipha_t) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7855
	    ipha->ipha_protocol != IPPROTO_TCP ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7856
	    (uchar_t *)tcph + ICMP_MIN_TCP_HDR > mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7857
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7858
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7860
	if (TCP_IS_DETACHED_NONEAGER(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7861
		if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7862
			secure = ipsec_in_is_secure(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7863
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7864
			secure = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7865
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7866
		if (secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7867
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7868
			 * If we are willing to accept this in clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7869
			 * we don't have to verify policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7870
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7871
			if (!ipsec_inbound_accept_clear(mp, ipha, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7872
				if (!tcp_check_policy(tcp, first_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7873
				    ipha, NULL, secure, ipsec_mctl)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7874
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7875
					 * tcp_check_policy called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7876
					 * ip_drop_packet() on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7877
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7878
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7879
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7880
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7881
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7882
	} else if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7883
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7884
		 * This is a hard_bound connection. IP has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7885
		 * verified policy. We don't have to do it again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7886
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7887
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7888
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7889
		ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7890
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7891
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7892
	seg_ack = ABE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7893
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7894
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7895
	 * TCP SHOULD check that the TCP sequence number contained in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7896
	 * payload of the ICMP error message is within the range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7897
	 * SND.UNA <= SEG.SEQ < SND.NXT. and also SEG.ACK <= RECV.NXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7898
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7899
	if (SEQ_LT(seg_seq, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7900
		SEQ_GEQ(seg_seq, tcp->tcp_snxt) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7901
		SEQ_GT(seg_ack, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7902
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7903
		 * If the ICMP message is bogus, should we kill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7904
		 * connection, or should we just drop the bogus ICMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7905
		 * message? It would probably make more sense to just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7906
		 * drop the message so that if this one managed to get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7907
		 * in, the real connection should not suffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7908
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7909
		goto noticmpv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7910
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7912
	switch (icmph->icmph_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7913
	case ICMP_DEST_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7914
		switch (icmph->icmph_code) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7915
		case ICMP_FRAGMENTATION_NEEDED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7916
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7917
			 * Reduce the MSS based on the new MTU.  This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7918
			 * eliminate any fragmentation locally.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7919
			 * N.B.  There may well be some funny side-effects on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7920
			 * the local send policy and the remote receive policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7921
			 * Pending further research, we provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7922
			 * tcp_ignore_path_mtu just in case this proves
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7923
			 * disastrous somewhere.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7924
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7925
			 * After updating the MSS, retransmit part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7926
			 * dropped segment using the new mss by calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7927
			 * tcp_wput_data().  Need to adjust all those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7928
			 * params to make sure tcp_wput_data() work properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7929
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7930
			if (tcp_ignore_path_mtu)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7931
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7932
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7933
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7934
			 * Decrease the MSS by time stamp options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7935
			 * IP options and IPSEC options. tcp_hdr_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7936
			 * includes time stamp option and IP option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7937
			 * length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7938
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7940
			new_mss = ntohs(icmph->icmph_du_mtu) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7941
			    tcp->tcp_hdr_len - tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7943
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7944
			 * Only update the MSS if the new one is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7945
			 * smaller than the previous one.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7946
			 * to avoid problems when getting multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7947
			 * ICMP errors for the same MTU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7948
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7949
			if (new_mss >= tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7950
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7951
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7952
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7953
			 * Stop doing PMTU if new_mss is less than 68
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7954
			 * or less than tcp_mss_min.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7955
			 * The value 68 comes from rfc 1191.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7956
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7957
			if (new_mss < MAX(68, tcp_mss_min))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7958
				tcp->tcp_ipha->ipha_fragment_offset_and_flags =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7959
				    0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7961
			ratio = tcp->tcp_cwnd / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7962
			ASSERT(ratio >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7963
			tcp_mss_set(tcp, new_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7965
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7966
			 * Make sure we have something to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7967
			 * send.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7968
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7969
			if (SEQ_LT(tcp->tcp_suna, tcp->tcp_snxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7970
			    (tcp->tcp_xmit_head != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7971
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7972
				 * Shrink tcp_cwnd in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7973
				 * proportion to the old MSS/new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7974
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7975
				tcp->tcp_cwnd = ratio * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7976
				if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7977
				    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7978
					tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7979
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7980
					tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7981
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7982
				tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7983
				tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7984
				tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7985
				tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7986
				tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7987
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7988
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7989
		case ICMP_PORT_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7990
		case ICMP_PROTOCOL_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7991
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7992
			case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7993
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7994
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7995
				 * ICMP can snipe away incipient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7996
				 * TCP connections as long as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7997
				 * seq number is same as initial
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7998
				 * send seq number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  7999
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8000
				if (seg_seq == tcp->tcp_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8001
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8002
					    ECONNREFUSED, 6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8003
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8004
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8005
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8006
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8007
		case ICMP_HOST_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8008
		case ICMP_NET_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8009
			/* Record the error in case we finally time out. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8010
			if (icmph->icmph_code == ICMP_HOST_UNREACHABLE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8011
				tcp->tcp_client_errno = EHOSTUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8012
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8013
				tcp->tcp_client_errno = ENETUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8014
			if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8015
				if (tcp->tcp_listener != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8016
				    tcp->tcp_listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8017
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8018
					 * Ditch the half-open connection if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8019
					 * suspect a SYN attack is under way.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8020
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8021
					tcp_ip_ire_mark_advice(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8022
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8023
					    tcp->tcp_client_errno, 7);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8024
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8025
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8026
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8027
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8028
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8029
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8030
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8031
	case ICMP_SOURCE_QUENCH: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8032
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8033
		 * use a global boolean to control
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8034
		 * whether TCP should respond to ICMP_SOURCE_QUENCH.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8035
		 * The default is false.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8036
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8037
		if (tcp_icmp_source_quench) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8038
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8039
			 * Reduce the sending rate as if we got a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8040
			 * retransmit timeout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8041
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8042
			uint32_t npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8043
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8044
			npkt = ((tcp->tcp_snxt - tcp->tcp_suna) >> 1) /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8045
			    tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8046
			tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8047
			tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8048
			tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8049
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8050
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8051
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8052
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8053
	freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8054
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8055
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8056
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8057
 * tcp_icmp_error_ipv6 is called by tcp_rput_other to process ICMPv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8058
 * error messages passed up by IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8059
 * Assumes that IP has pulled up all the extension headers as well
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8060
 * as the ICMPv6 header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8061
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8062
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8063
tcp_icmp_error_ipv6(tcp_t *tcp, mblk_t *mp, boolean_t ipsec_mctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8064
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8065
	icmp6_t *icmp6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8066
	ip6_t	*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8067
	uint16_t	iph_hdr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8068
	tcpha_t	*tcpha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8069
	uint8_t	*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8070
	uint32_t new_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8071
	uint32_t ratio;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8072
	boolean_t secure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8073
	mblk_t *first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8074
	size_t mp_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8075
	uint32_t seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8076
	uint32_t seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8078
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8079
	 * The caller has determined if this is an IPSEC_IN packet and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8080
	 * set ipsec_mctl appropriately (see tcp_icmp_error).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8081
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8082
	if (ipsec_mctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8083
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8085
	mp_size = MBLKL(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8087
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8088
	 * Verify that we have a complete IP header. If not, send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8089
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8090
	if (mp_size < sizeof (ip6_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8091
noticmpv6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8092
		freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8093
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8094
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8096
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8097
	 * Verify this is an ICMPV6 packet, else send it upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8098
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8099
	ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8100
	if (ip6h->ip6_nxt == IPPROTO_ICMPV6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8101
		iph_hdr_length = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8102
	} else if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8103
	    &nexthdrp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8104
	    *nexthdrp != IPPROTO_ICMPV6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8105
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8106
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8107
	icmp6 = (icmp6_t *)&mp->b_rptr[iph_hdr_length];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8108
	ip6h = (ip6_t *)&icmp6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8109
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8110
	 * Verify if we have a complete ICMP and inner IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8111
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8112
	if ((uchar_t *)&ip6h[1] > mp->b_wptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8113
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8115
	if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &iph_hdr_length, &nexthdrp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8116
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8117
	tcpha = (tcpha_t *)((char *)ip6h + iph_hdr_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8118
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8119
	 * Validate inner header. If the ULP is not IPPROTO_TCP or if we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8120
	 * have at least ICMP_MIN_TCP_HDR bytes of  TCP header drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8121
	 * packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8122
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8123
	if ((*nexthdrp != IPPROTO_TCP) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8124
	    ((uchar_t *)tcpha + ICMP_MIN_TCP_HDR) > mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8125
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8126
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8128
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8129
	 * ICMP errors come on the right queue or come on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8130
	 * listener/global queue for detached connections and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8131
	 * get switched to the right queue. If it comes on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8132
	 * right queue, policy check has already been done by IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8133
	 * and thus free the first_mp without verifying the policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8134
	 * If it has come for a non-hard bound connection, we need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8135
	 * to verify policy as IP may not have done it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8136
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8137
	if (!tcp->tcp_hard_bound) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8138
		if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8139
			secure = ipsec_in_is_secure(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8140
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8141
			secure = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8142
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8143
		if (secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8144
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8145
			 * If we are willing to accept this in clear
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8146
			 * we don't have to verify policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8147
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8148
			if (!ipsec_inbound_accept_clear(mp, NULL, ip6h)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8149
				if (!tcp_check_policy(tcp, first_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8150
				    NULL, ip6h, secure, ipsec_mctl)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8151
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8152
					 * tcp_check_policy called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8153
					 * ip_drop_packet() on failure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8154
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8155
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8156
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8157
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8158
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8159
	} else if (ipsec_mctl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8160
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8161
		 * This is a hard_bound connection. IP has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8162
		 * verified policy. We don't have to do it again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8163
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8164
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8165
		first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8166
		ipsec_mctl = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8167
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8169
	seg_ack = ntohl(tcpha->tha_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8170
	seg_seq = ntohl(tcpha->tha_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8171
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8172
	 * TCP SHOULD check that the TCP sequence number contained in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8173
	 * payload of the ICMP error message is within the range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8174
	 * SND.UNA <= SEG.SEQ < SND.NXT. and also SEG.ACK <= RECV.NXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8175
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8176
	if (SEQ_LT(seg_seq, tcp->tcp_suna) || SEQ_GEQ(seg_seq, tcp->tcp_snxt) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8177
	    SEQ_GT(seg_ack, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8178
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8179
		 * If the ICMP message is bogus, should we kill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8180
		 * connection, or should we just drop the bogus ICMP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8181
		 * message? It would probably make more sense to just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8182
		 * drop the message so that if this one managed to get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8183
		 * in, the real connection should not suffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8184
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8185
		goto noticmpv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8186
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8188
	switch (icmp6->icmp6_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8189
	case ICMP6_PACKET_TOO_BIG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8190
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8191
		 * Reduce the MSS based on the new MTU.  This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8192
		 * eliminate any fragmentation locally.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8193
		 * N.B.  There may well be some funny side-effects on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8194
		 * the local send policy and the remote receive policy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8195
		 * Pending further research, we provide
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8196
		 * tcp_ignore_path_mtu just in case this proves
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8197
		 * disastrous somewhere.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8198
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8199
		 * After updating the MSS, retransmit part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8200
		 * dropped segment using the new mss by calling
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8201
		 * tcp_wput_data().  Need to adjust all those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8202
		 * params to make sure tcp_wput_data() work properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8203
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8204
		if (tcp_ignore_path_mtu)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8205
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8207
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8208
		 * Decrease the MSS by time stamp options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8209
		 * IP options and IPSEC options. tcp_hdr_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8210
		 * includes time stamp option and IP option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8211
		 * length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8212
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8213
		new_mss = ntohs(icmp6->icmp6_mtu) - tcp->tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8214
			    tcp->tcp_ipsec_overhead;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8216
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8217
		 * Only update the MSS if the new one is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8218
		 * smaller than the previous one.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8219
		 * to avoid problems when getting multiple
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8220
		 * ICMP errors for the same MTU.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8221
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8222
		if (new_mss >= tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8223
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8225
		ratio = tcp->tcp_cwnd / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8226
		ASSERT(ratio >= 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8227
		tcp_mss_set(tcp, new_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8229
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8230
		 * Make sure we have something to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8231
		 * send.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8232
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8233
		if (SEQ_LT(tcp->tcp_suna, tcp->tcp_snxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8234
		    (tcp->tcp_xmit_head != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8235
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8236
			 * Shrink tcp_cwnd in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8237
			 * proportion to the old MSS/new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8238
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8239
			tcp->tcp_cwnd = ratio * tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8240
			if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8241
			    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8242
				tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8243
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8244
				tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8245
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8246
			tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8247
			tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8248
			tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8249
			tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8250
			tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8251
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8252
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8254
	case ICMP6_DST_UNREACH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8255
		switch (icmp6->icmp6_code) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8256
		case ICMP6_DST_UNREACH_NOPORT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8257
			if (((tcp->tcp_state == TCPS_SYN_SENT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8258
			    (tcp->tcp_state == TCPS_SYN_RCVD)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8259
			    (tcpha->tha_seq == tcp->tcp_iss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8260
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8261
				    ECONNREFUSED, 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8262
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8263
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8265
		case ICMP6_DST_UNREACH_ADMIN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8266
		case ICMP6_DST_UNREACH_NOROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8267
		case ICMP6_DST_UNREACH_BEYONDSCOPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8268
		case ICMP6_DST_UNREACH_ADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8269
			/* Record the error in case we finally time out. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8270
			tcp->tcp_client_errno = EHOSTUNREACH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8271
			if (((tcp->tcp_state == TCPS_SYN_SENT) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8272
			    (tcp->tcp_state == TCPS_SYN_RCVD)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8273
			    (tcpha->tha_seq == tcp->tcp_iss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8274
				if (tcp->tcp_listener != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8275
				    tcp->tcp_listener->tcp_syn_defense) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8276
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8277
					 * Ditch the half-open connection if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8278
					 * suspect a SYN attack is under way.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8279
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8280
					tcp_ip_ire_mark_advice(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8281
					(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8282
					    tcp->tcp_client_errno, 9);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8283
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8284
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8286
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8287
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8288
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8289
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8290
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8291
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8293
	case ICMP6_PARAM_PROB:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8294
		/* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8295
		if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8296
		    (uchar_t *)ip6h + icmp6->icmp6_pptr ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8297
		    (uchar_t *)nexthdrp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8298
			if (tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8299
			    tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8300
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8301
				    ECONNREFUSED, 10);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8302
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8303
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8304
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8305
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8307
	case ICMP6_TIME_EXCEEDED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8308
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8309
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8310
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8311
	freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8312
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8314
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8315
 * IP recognizes seven kinds of bind requests:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8316
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8317
 * - A zero-length address binds only to the protocol number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8318
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8319
 * - A 4-byte address is treated as a request to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8320
 * validate that the address is a valid local IPv4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8321
 * address, appropriate for an application to bind to.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8322
 * IP does the verification, but does not make any note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8323
 * of the address at this time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8324
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8325
 * - A 16-byte address contains is treated as a request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8326
 * to validate a local IPv6 address, as the 4-byte
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8327
 * address case above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8328
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8329
 * - A 16-byte sockaddr_in to validate the local IPv4 address and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8330
 * use it for the inbound fanout of packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8331
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8332
 * - A 24-byte sockaddr_in6 to validate the local IPv6 address and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8333
 * use it for the inbound fanout of packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8334
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8335
 * - A 12-byte address (ipa_conn_t) containing complete IPv4 fanout
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8336
 * information consisting of local and remote addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8337
 * and ports.  In this case, the addresses are both
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8338
 * validated as appropriate for this operation, and, if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8339
 * so, the information is retained for use in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8340
 * inbound fanout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8341
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8342
 * - A 36-byte address address (ipa6_conn_t) containing complete IPv6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8343
 * fanout information, like the 12-byte case above.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8344
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8345
 * IP will also fill in the IRE request mblk with information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8346
 * regarding our peer.  In all cases, we notify IP of our protocol
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8347
 * type by appending a single protocol byte to the bind request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8348
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8349
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8350
tcp_ip_bind_mp(tcp_t *tcp, t_scalar_t bind_prim, t_scalar_t addr_length)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8351
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8352
	char	*cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8353
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8354
	struct T_bind_req *tbr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8355
	ipa_conn_t	*ac;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8356
	ipa6_conn_t	*ac6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8357
	sin_t		*sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8358
	sin6_t		*sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8360
	ASSERT(bind_prim == O_T_BIND_REQ || bind_prim == T_BIND_REQ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8361
	ASSERT((tcp->tcp_family == AF_INET &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8362
	    tcp->tcp_ipversion == IPV4_VERSION) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8363
	    (tcp->tcp_family == AF_INET6 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8364
	    (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8365
	    tcp->tcp_ipversion == IPV6_VERSION)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8367
	mp = allocb(sizeof (*tbr) + addr_length + 1, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8368
	if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8369
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8370
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8371
	tbr = (struct T_bind_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8372
	tbr->PRIM_type = bind_prim;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8373
	tbr->ADDR_offset = sizeof (*tbr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8374
	tbr->CONIND_number = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8375
	tbr->ADDR_length = addr_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8376
	cp = (char *)&tbr[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8377
	switch (addr_length) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8378
	case sizeof (ipa_conn_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8379
		ASSERT(tcp->tcp_family == AF_INET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8380
		ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8382
		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8383
		if (mp->b_cont == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8384
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8385
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8386
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8387
		mp->b_cont->b_wptr += sizeof (ire_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8388
		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8390
		/* cp known to be 32 bit aligned */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8391
		ac = (ipa_conn_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8392
		ac->ac_laddr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8393
		ac->ac_faddr = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8394
		ac->ac_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8395
		ac->ac_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8396
		tcp->tcp_hard_binding = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8397
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8399
	case sizeof (ipa6_conn_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8400
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8401
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8402
		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8403
		if (mp->b_cont == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8404
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8405
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8406
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8407
		mp->b_cont->b_wptr += sizeof (ire_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8408
		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8409
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8410
		/* cp known to be 32 bit aligned */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8411
		ac6 = (ipa6_conn_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8412
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8413
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8414
			    &ac6->ac6_laddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8415
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8416
			ac6->ac6_laddr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8417
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8418
		ac6->ac6_faddr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8419
		ac6->ac6_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8420
		ac6->ac6_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8421
		tcp->tcp_hard_binding = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8422
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8424
	case sizeof (sin_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8425
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8426
		 * NOTE: IPV6_ADDR_LEN also has same size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8427
		 * Use family to discriminate.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8428
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8429
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8430
			sin = (sin_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8432
			*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8433
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8434
			sin->sin_addr.s_addr = tcp->tcp_bound_source;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8435
			sin->sin_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8436
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8437
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8438
			*(in6_addr_t *)cp = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8439
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8440
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8442
	case sizeof (sin6_t):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8443
		ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8444
		sin6 = (sin6_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8446
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8447
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8448
		sin6->sin6_addr = tcp->tcp_bound_source_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8449
		sin6->sin6_port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8450
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8451
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8452
	case IP_ADDR_LEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8453
		ASSERT(tcp->tcp_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8454
		*(uint32_t *)cp = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8455
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8457
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8458
	/* Add protocol number to end */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8459
	cp[addr_length] = (char)IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8460
	mp->b_wptr = (uchar_t *)&cp[addr_length + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8461
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8462
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8464
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8465
 * Notify IP that we are having trouble with this connection.  IP should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8466
 * blow the IRE away and start over.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8467
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8468
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8469
tcp_ip_notify(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8470
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8471
	struct iocblk	*iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8472
	ipid_t	*ipid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8473
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8474
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8475
	/* IPv6 has NUD thus notification to delete the IRE is not needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8476
	if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8477
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8479
	mp = mkiocb(IP_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8480
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8481
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8483
	iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8484
	iocp->ioc_count = sizeof (ipid_t) + sizeof (tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8486
	mp->b_cont = allocb(iocp->ioc_count, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8487
	if (!mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8488
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8489
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8490
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8492
	ipid = (ipid_t *)mp->b_cont->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8493
	mp->b_cont->b_wptr += iocp->ioc_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8494
	bzero(ipid, sizeof (*ipid));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8495
	ipid->ipid_cmd = IP_IOC_IRE_DELETE_NO_REPLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8496
	ipid->ipid_ire_type = IRE_CACHE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8497
	ipid->ipid_addr_offset = sizeof (ipid_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8498
	ipid->ipid_addr_length = sizeof (tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8499
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8500
	 * Note: in the case of source routing we want to blow away the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8501
	 * route to the first source route hop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8502
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8503
	bcopy(&tcp->tcp_ipha->ipha_dst, &ipid[1],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8504
	    sizeof (tcp->tcp_ipha->ipha_dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8505
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8506
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8507
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8509
/* Unlink and return any mblk that looks like it contains an ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8510
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8511
tcp_ire_mp(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8512
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8513
	mblk_t	*prev_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8515
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8516
		prev_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8517
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8518
		if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8519
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8520
		switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8521
		case IRE_DB_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8522
		case IRE_DB_REQ_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8523
			if (prev_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8524
				prev_mp->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8525
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8526
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8527
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8528
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8529
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8530
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8531
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8532
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8533
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8534
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8535
 * Timer callback routine for keepalive probe.  We do a fake resend of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8536
 * last ACKed byte.  Then set a timer using RTO.  When the timer expires,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8537
 * check to see if we have heard anything from the other end for the last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8538
 * RTO period.  If we have, set the timer to expire for another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8539
 * tcp_keepalive_intrvl and check again.  If we have not, set a timer using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8540
 * RTO << 1 and check again when it expires.  Keep exponentially increasing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8541
 * the timeout if we have not heard from the other side.  If for more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8542
 * (tcp_ka_interval + tcp_ka_abort_thres) we have not heard anything,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8543
 * kill the connection unless the keepalive abort threshold is 0.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8544
 * that case, we will probe "forever."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8545
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8546
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8547
tcp_keepalive_killer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8548
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8549
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8550
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8551
	tcp_t  	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8552
	int32_t	firetime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8553
	int32_t	idletime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8554
	int32_t	ka_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8556
	tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8558
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8559
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8561
	BUMP_MIB(&tcp_mib, tcpTimKeepalive);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8562
	ka_intrvl = tcp->tcp_ka_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8564
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8565
	 * Keepalive probe should only be sent if the application has not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8566
	 * done a close on the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8567
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8568
	if (tcp->tcp_state > TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8569
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8570
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8571
	/* Timer fired too early, restart it. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8572
	if (tcp->tcp_state < TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8573
		tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8574
		    MSEC_TO_TICK(ka_intrvl));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8575
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8576
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8578
	idletime = TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8579
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8580
	 * If we have not heard from the other side for a long
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8581
	 * time, kill the connection unless the keepalive abort
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8582
	 * threshold is 0.  In that case, we will probe "forever."
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8583
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8584
	if (tcp->tcp_ka_abort_thres != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8585
	    idletime > (ka_intrvl + tcp->tcp_ka_abort_thres)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8586
		BUMP_MIB(&tcp_mib, tcpTimKeepaliveDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8587
		(void) tcp_clean_death(tcp, tcp->tcp_client_errno ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8588
		    tcp->tcp_client_errno : ETIMEDOUT, 11);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8589
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8590
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8592
	if (tcp->tcp_snxt == tcp->tcp_suna &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8593
	    idletime >= ka_intrvl) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8594
		/* Fake resend of last ACKed byte. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8595
		mblk_t	*mp1 = allocb(1, BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8597
		if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8598
			*mp1->b_wptr++ = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8599
			mp = tcp_xmit_mp(tcp, mp1, 1, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8600
			    tcp->tcp_suna - 1, B_FALSE, NULL, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8601
			freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8602
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8603
			 * if allocation failed, fall through to start the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8604
			 * timer back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8605
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8606
			if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8607
				TCP_RECORD_TRACE(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8608
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8609
				tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8610
				BUMP_MIB(&tcp_mib, tcpTimKeepaliveProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8611
				if (tcp->tcp_ka_last_intrvl != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8612
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8613
					 * We should probe again at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8614
					 * in ka_intrvl, but not more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8615
					 * tcp_rexmit_interval_max.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8616
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8617
					firetime = MIN(ka_intrvl - 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8618
					    tcp->tcp_ka_last_intrvl << 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8619
					if (firetime > tcp_rexmit_interval_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8620
						firetime =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8621
						    tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8622
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8623
					firetime = tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8624
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8625
				tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8626
				    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8627
				    MSEC_TO_TICK(firetime));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8628
				tcp->tcp_ka_last_intrvl = firetime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8629
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8630
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8631
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8632
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8633
		tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8634
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8636
	/* firetime can be negative if (mp1 == NULL || mp == NULL) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8637
	if ((firetime = ka_intrvl - idletime) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8638
		firetime = ka_intrvl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8639
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8640
	tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8641
	    MSEC_TO_TICK(firetime));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8642
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8643
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8644
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8645
tcp_maxpsz_set(tcp_t *tcp, boolean_t set_maxblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8646
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8647
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8648
	int32_t	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8649
	int	maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8651
	if (TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8652
		return (mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8653
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8654
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8655
		maxpsz = tcp_fuse_maxpsz_set(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8656
		mss = INFPSZ;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  8657
	} else if (tcp->tcp_mdt || tcp->tcp_maxpsz == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8658
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8659
		 * Set the sd_qn_maxpsz according to the socket send buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8660
		 * size, and sd_maxblk to INFPSZ (-1).  This will essentially
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8661
		 * instruct the stream head to copyin user data into contiguous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8662
		 * kernel-allocated buffers without breaking it up into smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8663
		 * chunks.  We round up the buffer size to the nearest SMSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8664
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8665
		maxpsz = MSS_ROUNDUP(tcp->tcp_xmit_hiwater, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8666
		mss = INFPSZ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8667
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8668
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8669
		 * Set sd_qn_maxpsz to approx half the (receivers) buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8670
		 * (and a multiple of the mss).  This instructs the stream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8671
		 * head to break down larger than SMSS writes into SMSS-
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8672
		 * size mblks, up to tcp_maxpsz_multiplier mblks at a time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8673
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8674
		maxpsz = tcp->tcp_maxpsz * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8675
		if (maxpsz > tcp->tcp_xmit_hiwater/2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8676
			maxpsz = tcp->tcp_xmit_hiwater/2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8677
			/* Round up to nearest mss */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8678
			maxpsz = MSS_ROUNDUP(maxpsz, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8679
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8680
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8681
	(void) setmaxps(q, maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8682
	tcp->tcp_wq->q_maxpsz = maxpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8684
	if (set_maxblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8685
		(void) mi_set_sth_maxblk(q, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8687
	return (mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8688
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8690
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8691
 * Extract option values from a tcp header.  We put any found values into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8692
 * tcpopt struct and return a bitmask saying which options were found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8693
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8694
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8695
tcp_parse_options(tcph_t *tcph, tcp_opt_t *tcpopt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8696
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8697
	uchar_t		*endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8698
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8699
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8700
	uchar_t		*up = (uchar_t *)tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8701
	int		found = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8702
	int32_t		sack_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8703
	tcp_seq		sack_begin, sack_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8704
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8706
	endp = up + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8707
	up += TCP_MIN_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8708
	while (up < endp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8709
		len = endp - up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8710
		switch (*up) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8711
		case TCPOPT_EOL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8712
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8714
		case TCPOPT_NOP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8715
			up++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8716
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8717
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8718
		case TCPOPT_MAXSEG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8719
			if (len < TCPOPT_MAXSEG_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8720
			    up[1] != TCPOPT_MAXSEG_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8721
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8723
			mss = BE16_TO_U16(up+2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8724
			/* Caller must handle tcp_mss_min and tcp_mss_max_* */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8725
			tcpopt->tcp_opt_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8726
			found |= TCP_OPT_MSS_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8727
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8728
			up += TCPOPT_MAXSEG_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8729
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8731
		case TCPOPT_WSCALE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8732
			if (len < TCPOPT_WS_LEN || up[1] != TCPOPT_WS_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8733
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8734
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8735
			if (up[2] > TCP_MAX_WINSHIFT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8736
				tcpopt->tcp_opt_wscale = TCP_MAX_WINSHIFT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8737
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8738
				tcpopt->tcp_opt_wscale = up[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8739
			found |= TCP_OPT_WSCALE_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8740
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8741
			up += TCPOPT_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8742
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8744
		case TCPOPT_SACK_PERMITTED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8745
			if (len < TCPOPT_SACK_OK_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8746
			    up[1] != TCPOPT_SACK_OK_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8747
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8748
			found |= TCP_OPT_SACK_OK_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8749
			up += TCPOPT_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8750
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8752
		case TCPOPT_SACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8753
			if (len <= 2 || up[1] <= 2 || len < up[1])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8754
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8756
			/* If TCP is not interested in SACK blks... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8757
			if ((tcp = tcpopt->tcp) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8758
				up += up[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8759
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8760
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8761
			sack_len = up[1] - TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8762
			up += TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8763
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8764
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8765
			 * If the list is empty, allocate one and assume
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8766
			 * nothing is sack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8767
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8768
			ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8769
			if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8770
				tcp_notsack_update(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8771
				    tcp->tcp_suna, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8772
				    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8773
				    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8775
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8776
				 * Make sure tcp_notsack_list is not NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8777
				 * This happens when kmem_alloc(KM_NOSLEEP)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8778
				 * returns NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8779
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8780
				if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8781
					up += sack_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8782
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8783
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8784
				tcp->tcp_fack = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8785
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8786
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8787
			while (sack_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8788
				if (up + 8 > endp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8789
					up = endp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8790
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8791
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8792
				sack_begin = BE32_TO_U32(up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8793
				up += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8794
				sack_end = BE32_TO_U32(up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8795
				up += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8796
				sack_len -= 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8797
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8798
				 * Bounds checking.  Make sure the SACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8799
				 * info is within tcp_suna and tcp_snxt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8800
				 * If this SACK blk is out of bound, ignore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8801
				 * it but continue to parse the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8802
				 * blks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8803
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8804
				if (SEQ_LEQ(sack_end, sack_begin) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8805
				    SEQ_LT(sack_begin, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8806
				    SEQ_GT(sack_end, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8807
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8808
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8809
				tcp_notsack_insert(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8810
				    sack_begin, sack_end,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8811
				    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8812
				    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8813
				if (SEQ_GT(sack_end, tcp->tcp_fack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8814
					tcp->tcp_fack = sack_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8815
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8816
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8817
			found |= TCP_OPT_SACK_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8818
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8819
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8820
		case TCPOPT_TSTAMP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8821
			if (len < TCPOPT_TSTAMP_LEN ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8822
			    up[1] != TCPOPT_TSTAMP_LEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8823
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8824
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8825
			tcpopt->tcp_opt_ts_val = BE32_TO_U32(up+2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8826
			tcpopt->tcp_opt_ts_ecr = BE32_TO_U32(up+6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8828
			found |= TCP_OPT_TSTAMP_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8829
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8830
			up += TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8831
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8833
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8834
			if (len <= 1 || len < (int)up[1] || up[1] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8835
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8836
			up += up[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8837
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8838
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8839
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8840
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8841
	return (found);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8842
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8844
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8845
 * Set the mss associated with a particular tcp based on its current value,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8846
 * and a new one passed in. Observe minimums and maximums, and reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8847
 * other state variables that we want to view as multiples of mss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8848
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8849
 * This function is called in various places mainly because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8850
 * 1) Various stuffs, tcp_mss, tcp_cwnd, ... need to be adjusted when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8851
 *    other side's SYN/SYN-ACK packet arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8852
 * 2) PMTUd may get us a new MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8853
 * 3) If the other side stops sending us timestamp option, we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8854
 *    increase the MSS size to use the extra bytes available.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8855
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8856
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8857
tcp_mss_set(tcp_t *tcp, uint32_t mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8858
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8859
	uint32_t	mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8861
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8862
		mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8863
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8864
		mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8865
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8866
	if (mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8867
		mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8868
	if (mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8869
		mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8870
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8871
	 * Unless naglim has been set by our client to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8872
	 * a non-mss value, force naglim to track mss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8873
	 * This can help to aggregate small writes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8874
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8875
	if (mss < tcp->tcp_naglim || tcp->tcp_mss == tcp->tcp_naglim)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8876
		tcp->tcp_naglim = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8877
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8878
	 * TCP should be able to buffer at least 4 MSS data for obvious
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8879
	 * performance reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8880
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8881
	if ((mss << 2) > tcp->tcp_xmit_hiwater)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8882
		tcp->tcp_xmit_hiwater = mss << 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8883
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8884
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8885
	 * Check if we need to apply the tcp_init_cwnd here.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8886
	 * it is set and the MSS gets bigger (should not happen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8887
	 * normally), we need to adjust the resulting tcp_cwnd properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8888
	 * The new tcp_cwnd should not get bigger.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8889
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8890
	if (tcp->tcp_init_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8891
		tcp->tcp_cwnd = MIN(tcp_slow_start_initial * mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8892
		    MIN(4 * mss, MAX(2 * mss, 4380 / mss * mss)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8893
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8894
		if (tcp->tcp_mss < mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8895
			tcp->tcp_cwnd = MAX(1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8896
			    (tcp->tcp_init_cwnd * tcp->tcp_mss / mss)) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8897
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8898
			tcp->tcp_cwnd = tcp->tcp_init_cwnd * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8899
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8900
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8901
	tcp->tcp_mss = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8902
	tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8903
	(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8904
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8906
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8907
tcp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8908
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8909
	tcp_t		*tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8910
	conn_t		*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8911
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8912
	dev_t		conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8913
	zoneid_t	zoneid = getzoneid();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8915
	if (q->q_ptr != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8916
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8917
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8918
	if (sflag == MODOPEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8919
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8920
		 * This is a special case. The purpose of a modopen
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8921
		 * is to allow just the T_SVR4_OPTMGMT_REQ to pass
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8922
		 * through for MIB browsers. Everything else is failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8923
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8924
		connp = (conn_t *)tcp_get_conn(IP_SQUEUE_GET(lbolt));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8925
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8926
		if (connp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8927
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8928
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8929
		connp->conn_flags |= IPCL_TCPMOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8930
		connp->conn_cred = credp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8931
		connp->conn_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8932
		q->q_ptr = WR(q)->q_ptr = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8933
		crhold(credp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8934
		q->q_qinfo = &tcp_mod_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8935
		WR(q)->q_qinfo = &tcp_mod_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8936
		qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8937
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8938
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8939
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8940
	if ((conn_dev = inet_minor_alloc(ip_minor_arena)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8941
		return (EBUSY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8942
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8943
	*devp = makedevice(getemajor(*devp), (minor_t)conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8945
	if (flag & SO_ACCEPTOR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8946
		q->q_qinfo = &tcp_acceptor_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8947
		q->q_ptr = (void *)conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8948
		WR(q)->q_qinfo = &tcp_acceptor_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8949
		WR(q)->q_ptr = (void *)conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8950
		qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8951
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8952
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8953
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8954
	connp = (conn_t *)tcp_get_conn(IP_SQUEUE_GET(lbolt));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8955
	if (connp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8956
		inet_minor_free(ip_minor_arena, conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8957
		q->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8958
		return (ENOSR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8959
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8960
	connp->conn_sqp = IP_SQUEUE_GET(lbolt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8961
	tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8963
	q->q_ptr = WR(q)->q_ptr = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8964
	if (getmajor(*devp) == TCP6_MAJ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8965
		connp->conn_flags |= (IPCL_TCP6|IPCL_ISV6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8966
		connp->conn_send = ip_output_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8967
		connp->conn_af_isv6 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8968
		connp->conn_pkt_isv6 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8969
		connp->conn_src_preferences = IPV6_PREFER_SRC_DEFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8970
		tcp->tcp_ipversion = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8971
		tcp->tcp_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8972
		tcp->tcp_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8973
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8974
		connp->conn_flags |= IPCL_TCP4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8975
		connp->conn_send = ip_output;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8976
		connp->conn_af_isv6 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8977
		connp->conn_pkt_isv6 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8978
		tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8979
		tcp->tcp_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8980
		tcp->tcp_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8981
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8983
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8984
	 * TCP keeps a copy of cred for cache locality reasons but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8985
	 * we put a reference only once. If connp->conn_cred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8986
	 * becomes invalid, tcp_cred should also be set to NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8987
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8988
	tcp->tcp_cred = connp->conn_cred = credp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8989
	crhold(connp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8990
	tcp->tcp_cpid = curproc->p_pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8991
	connp->conn_zoneid = zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8993
	connp->conn_dev = conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8995
	ASSERT(q->q_qinfo == &tcp_rinit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8996
	ASSERT(WR(q)->q_qinfo == &tcp_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8998
	if (flag & SO_SOCKSTR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  8999
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9000
		 * No need to insert a socket in tcp acceptor hash.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9001
		 * If it was a socket acceptor stream, we dealt with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9002
		 * it above. A socket listener can never accept a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9003
		 * connection and doesn't need acceptor_id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9004
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9005
		connp->conn_flags |= IPCL_SOCKET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9006
		tcp->tcp_issocket = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9007
		WR(q)->q_qinfo = &tcp_sock_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9008
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9009
#ifdef	_ILP32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9010
		tcp->tcp_acceptor_id = (t_uscalar_t)RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9011
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9012
		tcp->tcp_acceptor_id = conn_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9013
#endif	/* _ILP32 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9014
		tcp_acceptor_hash_insert(tcp->tcp_acceptor_id, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9015
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9017
	if (tcp_trace)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9018
		tcp->tcp_tracebuf = kmem_zalloc(sizeof (tcptrch_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9020
	err = tcp_init(tcp, q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9021
	if (err != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9022
		inet_minor_free(ip_minor_arena, connp->conn_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9023
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9024
		CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9025
		q->q_ptr = WR(q)->q_ptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9026
		return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9027
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9028
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9029
	RD(q)->q_hiwat = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9030
	tcp->tcp_rwnd = tcp_recv_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9032
	/* Non-zero default values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9033
	connp->conn_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9034
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9035
	 * Put the ref for TCP. Ref for IP was already put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9036
	 * by ipcl_conn_create. Also Make the conn_t globally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9037
	 * visible to walkers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9038
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9039
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9040
	CONN_INC_REF_LOCKED(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9041
	ASSERT(connp->conn_ref == 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9042
	connp->conn_state_flags &= ~CONN_INCIPIENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9043
	mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9045
	qprocson(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9046
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9047
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9049
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9050
 * Some TCP options can be "set" by requesting them in the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9051
 * buffer. This is needed for XTI feature test though we do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9052
 * allow it in general. We interpret that this mechanism is more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9053
 * applicable to OSI protocols and need not be allowed in general.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9054
 * This routine filters out options for which it is not allowed (most)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9055
 * and lets through those (few) for which it is. [ The XTI interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9056
 * test suite specifics will imply that any XTI_GENERIC level XTI_* if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9057
 * ever implemented will have to be allowed here ].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9058
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9059
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9060
tcp_allow_connopt_set(int level, int name)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9061
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9063
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9064
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9065
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9066
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9067
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9068
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9069
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9070
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9071
		/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9072
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9073
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9074
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9075
	/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9076
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9077
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9078
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9079
 * This routine gets default values of certain options whose default
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9080
 * values are maintained by protocol specific code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9081
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9082
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9083
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9084
tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9085
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9086
	int32_t	*i1 = (int32_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9088
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9089
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9090
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9091
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9092
			*i1 = tcp_ip_notify_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9093
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9094
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9095
			*i1 = tcp_ip_abort_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9096
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9097
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9098
			*i1 = tcp_ip_notify_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9099
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9100
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9101
			*i1 = tcp_ip_abort_cinterval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9102
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9103
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9104
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9105
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9106
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9107
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9108
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9109
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9110
			*i1 = tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9111
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9112
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9113
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9114
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9115
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9116
	case IPPROTO_IPV6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9117
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9118
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9119
			*i1 = tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9120
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9121
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9122
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9123
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9124
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9125
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9126
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9127
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9128
	return (sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9129
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9132
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9133
 * TCP routine to get the values of options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9134
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9135
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9136
tcp_opt_get(queue_t *q, int level, int	name, uchar_t *ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9137
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9138
	int		*i1 = (int *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9139
	conn_t		*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9140
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9141
	ip6_pkt_t	*ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9143
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9144
	case SOL_SOCKET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9145
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9146
		case SO_LINGER:	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9147
			struct linger *lgr = (struct linger *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9149
			lgr->l_onoff = tcp->tcp_linger ? SO_LINGER : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9150
			lgr->l_linger = tcp->tcp_lingertime;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9151
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9152
			return (sizeof (struct linger));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9153
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9154
			*i1 = tcp->tcp_debug ? SO_DEBUG : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9155
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9156
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9157
			*i1 = tcp->tcp_ka_enabled ? SO_KEEPALIVE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9158
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9159
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9160
			*i1 = tcp->tcp_dontroute ? SO_DONTROUTE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9161
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9162
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9163
			*i1 = tcp->tcp_useloopback ? SO_USELOOPBACK : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9164
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9165
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9166
			*i1 = tcp->tcp_broadcast ? SO_BROADCAST : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9167
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9168
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9169
			*i1 = tcp->tcp_reuseaddr ? SO_REUSEADDR : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9170
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9171
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9172
			*i1 = tcp->tcp_oobinline ? SO_OOBINLINE : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9173
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9174
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9175
			*i1 = tcp->tcp_dgram_errind ? SO_DGRAM_ERRIND : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9176
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9177
		case SO_TYPE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9178
			*i1 = SOCK_STREAM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9179
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9180
		case SO_SNDBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9181
			*i1 = tcp->tcp_xmit_hiwater;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9182
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9183
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9184
			*i1 = RD(q)->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9185
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9186
		case SO_SND_COPYAVOID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9187
			*i1 = tcp->tcp_snd_zcopy_on ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9188
			    SO_SND_COPYAVOID : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9189
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9190
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9191
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9192
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9193
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9194
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9195
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9196
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9197
			*i1 = (tcp->tcp_naglim == 1) ? TCP_NODELAY : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9198
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9199
		case TCP_MAXSEG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9200
			*i1 = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9201
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9202
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9203
			*i1 = (int)tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9204
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9205
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9206
			*i1 = tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9207
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9208
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9209
			*i1 = tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9210
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9211
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9212
			*i1 = tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9213
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9214
		case TCP_RECVDSTADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9215
			*i1 = tcp->tcp_recvdstaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9216
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9217
		case TCP_ANONPRIVBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9218
			*i1 = tcp->tcp_anon_priv_bind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9219
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9220
		case TCP_EXCLBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9221
			*i1 = tcp->tcp_exclbind ? TCP_EXCLBIND : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9222
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9223
		case TCP_INIT_CWND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9224
			*i1 = tcp->tcp_init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9225
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9226
		case TCP_KEEPALIVE_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9227
			*i1 = tcp->tcp_ka_interval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9228
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9229
		case TCP_KEEPALIVE_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9230
			*i1 = tcp->tcp_ka_abort_thres;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9231
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9232
		case TCP_CORK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9233
			*i1 = tcp->tcp_cork;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9234
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9235
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9236
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9237
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9238
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9239
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9240
		if (tcp->tcp_family != AF_INET)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9241
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9242
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9243
		case IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9244
		case T_IP_OPTIONS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9245
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9246
			 * This is compatible with BSD in that in only return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9247
			 * the reverse source route with the final destination
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9248
			 * as the last entry. The first 4 bytes of the option
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9249
			 * will contain the final destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9250
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9251
			char	*opt_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9252
			int	opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9253
			opt_ptr = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9254
			opt_len = (char *)tcp->tcp_tcph - opt_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9255
			/* Caller ensures enough space */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9256
			if (opt_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9257
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9258
				 * TODO: Do we have to handle getsockopt on an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9259
				 * initiator as well?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9260
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9261
				return (tcp_opt_get_user(tcp->tcp_ipha, ptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9262
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9263
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9264
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9265
		case IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9266
		case T_IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9267
			*i1 = (int)tcp->tcp_ipha->ipha_type_of_service;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9268
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9269
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9270
			*i1 = (int)tcp->tcp_ipha->ipha_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9271
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9272
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9273
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9274
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9275
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9276
	case IPPROTO_IPV6:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9277
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9278
		 * IPPROTO_IPV6 options are only supported for sockets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9279
		 * that are using IPv6 on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9280
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9281
		if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9282
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9283
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9284
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9285
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9286
			*i1 = (unsigned int) tcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9287
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9288
		case IPV6_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9289
			/* Zero if not set */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9290
			*i1 = tcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9291
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9292
		case IPV6_RECVPKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9293
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9294
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9295
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9296
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9297
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9298
		case IPV6_RECVTCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9299
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVTCLASS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9300
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9301
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9302
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9303
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9304
		case IPV6_RECVHOPLIMIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9305
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9306
			    TCP_IPV6_RECVHOPLIMIT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9307
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9308
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9309
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9310
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9311
		case IPV6_RECVHOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9312
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9313
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9314
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9315
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9316
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9317
		case IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9318
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9319
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9320
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9321
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9322
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9323
		case _OLD_IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9324
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9325
			    TCP_OLD_IPV6_RECVDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9326
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9327
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9328
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9329
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9330
		case IPV6_RECVRTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9331
			if (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTHDR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9332
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9333
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9334
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9335
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9336
		case IPV6_RECVRTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9337
			if (tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9338
			    TCP_IPV6_RECVRTDSTOPTS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9339
				*i1 = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9340
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9341
				*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9342
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9343
		case IPV6_PKTINFO: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9344
			/* XXX assumes that caller has room for max size! */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9345
			struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9347
			pkti = (struct in6_pktinfo *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9348
			if (ipp->ipp_fields & IPPF_IFINDEX)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9349
				pkti->ipi6_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9350
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9351
				pkti->ipi6_ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9352
			if (ipp->ipp_fields & IPPF_ADDR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9353
				pkti->ipi6_addr = ipp->ipp_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9354
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9355
				pkti->ipi6_addr = ipv6_all_zeros;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9356
			return (sizeof (struct in6_pktinfo));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9357
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9358
		case IPV6_TCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9359
			if (ipp->ipp_fields & IPPF_TCLASS)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9360
				*i1 = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9361
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9362
				*i1 = IPV6_FLOW_TCLASS(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9363
				    IPV6_DEFAULT_VERS_AND_FLOW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9364
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9365
		case IPV6_NEXTHOP: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9366
			sin6_t *sin6 = (sin6_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9367
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9368
			if (!(ipp->ipp_fields & IPPF_NEXTHOP))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9369
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9370
			*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9371
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9372
			sin6->sin6_addr = ipp->ipp_nexthop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9373
			return (sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9374
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9375
		case IPV6_HOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9376
			if (!(ipp->ipp_fields & IPPF_HOPOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9377
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9378
			bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9379
			return (ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9380
		case IPV6_RTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9381
			if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9382
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9383
			bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9384
			return (ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9385
		case IPV6_RTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9386
			if (!(ipp->ipp_fields & IPPF_RTHDR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9387
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9388
			bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9389
			return (ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9390
		case IPV6_DSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9391
			if (!(ipp->ipp_fields & IPPF_DSTOPTS))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9392
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9393
			bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9394
			return (ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9395
		case IPV6_SRC_PREFERENCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9396
			return (ip6_get_src_preferences(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9397
			    (uint32_t *)ptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9398
		case IPV6_PATHMTU: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9399
			struct ip6_mtuinfo *mtuinfo = (struct ip6_mtuinfo *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9401
			if (tcp->tcp_state < TCPS_ESTABLISHED)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9402
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9404
			return (ip_fill_mtuinfo(&connp->conn_remv6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9405
				connp->conn_fport, mtuinfo));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9406
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9407
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9408
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9409
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9410
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9411
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9412
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9413
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9414
	return (sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9415
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9417
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9418
 * We declare as 'int' rather than 'void' to satisfy pfi_t arg requirements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9419
 * Parameters are assumed to be verified by the caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9420
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9421
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9422
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9423
tcp_opt_set(queue_t *q, uint_t optset_context, int level, int name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9424
    uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9425
    void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9426
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9427
	tcp_t	*tcp = Q_TO_TCP(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9428
	int	*i1 = (int *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9429
	boolean_t onoff = (*i1 == 0) ? 0 : 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9430
	boolean_t checkonly;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9431
	int	reterr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9433
	switch (optset_context) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9434
	case SETFN_OPTCOM_CHECKONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9435
		checkonly = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9436
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9437
		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9438
		 * inlen != 0 implies value supplied and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9439
		 * 	we have to "pretend" to set it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9440
		 * inlen == 0 implies that there is no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9441
		 * 	value part in T_CHECK request and just validation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9442
		 * done elsewhere should be enough, we just return here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9443
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9444
		if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9445
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9446
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9447
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9448
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9449
	case SETFN_OPTCOM_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9450
		checkonly = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9451
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9452
	case SETFN_UD_NEGOTIATE: /* error on conn-oriented transports ? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9453
	case SETFN_CONN_NEGOTIATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9454
		checkonly = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9455
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9456
		 * Negotiating local and "association-related" options
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9457
		 * from other (T_CONN_REQ, T_CONN_RES,T_UNITDATA_REQ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9458
		 * primitives is allowed by XTI, but we choose
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9459
		 * to not implement this style negotiation for Internet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9460
		 * protocols (We interpret it is a must for OSI world but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9461
		 * optional for Internet protocols) for all options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9462
		 * [ Will do only for the few options that enable test
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9463
		 * suites that our XTI implementation of this feature
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9464
		 * works for transports that do allow it ]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9465
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9466
		if (!tcp_allow_connopt_set(level, name)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9467
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9468
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9469
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9470
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9471
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9472
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9473
		 * We should never get here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9474
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9475
		*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9476
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9477
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9479
	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9480
	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9482
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9483
	 * For TCP, we should have no ancillary data sent down
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9484
	 * (sendmsg isn't supported for SOCK_STREAM), so thisdg_attrs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9485
	 * has to be zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9486
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9487
	ASSERT(thisdg_attrs == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9488
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9489
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9490
	 * For fixed length options, no sanity check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9491
	 * of passed in length is done. It is assumed *_optcom_req()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9492
	 * routines do the right thing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9493
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9495
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9496
	case SOL_SOCKET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9497
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9498
		case SO_LINGER: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9499
			struct linger *lgr = (struct linger *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9500
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9501
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9502
				if (lgr->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9503
					tcp->tcp_linger = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9504
					tcp->tcp_lingertime = lgr->l_linger;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9505
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9506
					tcp->tcp_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9507
					tcp->tcp_lingertime = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9508
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9509
				/* struct copy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9510
				*(struct linger *)outvalp = *lgr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9511
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9512
				if (!lgr->l_onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9513
				    ((struct linger *)outvalp)->l_onoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9514
				    ((struct linger *)outvalp)->l_linger = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9515
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9516
				    /* struct copy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9517
				    *(struct linger *)outvalp = *lgr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9518
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9519
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9520
			*outlenp = sizeof (struct linger);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9521
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9522
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9523
		case SO_DEBUG:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9524
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9525
				tcp->tcp_debug = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9526
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9527
		case SO_KEEPALIVE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9528
			if (checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9529
				/* T_CHECK case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9530
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9531
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9532
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9533
			if (!onoff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9534
				if (tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9535
					if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9536
						(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9537
						    tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9538
						tcp->tcp_ka_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9539
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9540
					tcp->tcp_ka_enabled = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9541
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9542
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9543
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9544
			if (!tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9545
				/* Crank up the keepalive timer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9546
				tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9547
				tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9548
				    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9549
				    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9550
				tcp->tcp_ka_enabled = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9551
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9552
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9553
		case SO_DONTROUTE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9554
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9555
			 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9556
			 * only of interest to IP.  We track them here only so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9557
			 * that we can report their current value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9558
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9559
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9560
				tcp->tcp_dontroute = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9561
				tcp->tcp_connp->conn_dontroute = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9562
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9563
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9564
		case SO_USELOOPBACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9565
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9566
				tcp->tcp_useloopback = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9567
				tcp->tcp_connp->conn_loopback = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9568
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9569
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9570
		case SO_BROADCAST:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9571
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9572
				tcp->tcp_broadcast = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9573
				tcp->tcp_connp->conn_broadcast = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9574
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9575
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9576
		case SO_REUSEADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9577
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9578
				tcp->tcp_reuseaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9579
				tcp->tcp_connp->conn_reuseaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9580
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9581
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9582
		case SO_OOBINLINE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9583
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9584
				tcp->tcp_oobinline = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9585
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9586
		case SO_DGRAM_ERRIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9587
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9588
				tcp->tcp_dgram_errind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9589
			break;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9590
		case SO_SNDBUF: {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9591
			tcp_t *peer_tcp;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9592
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9593
			if (*i1 > tcp_max_buf) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9594
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9595
				return (ENOBUFS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9596
			}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9597
			if (checkonly)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9598
				break;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9599
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9600
			tcp->tcp_xmit_hiwater = *i1;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9601
			if (tcp_snd_lowat_fraction != 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9602
				tcp->tcp_xmit_lowater =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9603
				    tcp->tcp_xmit_hiwater /
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9604
				    tcp_snd_lowat_fraction;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9605
			(void) tcp_maxpsz_set(tcp, B_TRUE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9606
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9607
			 * If we are flow-controlled, recheck the condition.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9608
			 * There are apps that increase SO_SNDBUF size when
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9609
			 * flow-controlled (EWOULDBLOCK), and expect the flow
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9610
			 * control condition to be lifted right away.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9611
			 *
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9612
			 * For the fused tcp loopback case, in order to avoid
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9613
			 * a race with the peer's tcp_fuse_rrw() we need to
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9614
			 * hold its fuse_lock while accessing tcp_flow_stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9615
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9616
			peer_tcp = tcp->tcp_loopback_peer;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9617
			ASSERT(!tcp->tcp_fused || peer_tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9618
			if (tcp->tcp_fused)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9619
				mutex_enter(&peer_tcp->tcp_fuse_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9620
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9621
			if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9622
			    TCP_UNSENT_BYTES(tcp) < tcp->tcp_xmit_hiwater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9623
				tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9624
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9625
			if (tcp->tcp_fused)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9626
				mutex_exit(&peer_tcp->tcp_fuse_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9627
			break;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
  9628
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9629
		case SO_RCVBUF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9630
			if (*i1 > tcp_max_buf) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9631
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9632
				return (ENOBUFS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9633
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9634
			/* Silently ignore zero */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9635
			if (!checkonly && *i1 != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9636
				*i1 = MSS_ROUNDUP(*i1, tcp->tcp_mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9637
				(void) tcp_rwnd_set(tcp, *i1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9638
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9639
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9640
			 * XXX should we return the rwnd here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9641
			 * and tcp_opt_get ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9642
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9643
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9644
		case SO_SND_COPYAVOID:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9645
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9646
				/* we only allow enable at most once for now */
184
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9647
				if (tcp->tcp_loopback ||
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9648
				    (!tcp->tcp_snd_zcopy_aware &&
2b3e636dbda4 6294490 snf_segmap hangs on loopback connection
xy158873
parents: 0
diff changeset
  9649
				    (onoff != 1 || !tcp_zcopy_check(tcp)))) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9650
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9651
					return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9652
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9653
				tcp->tcp_snd_zcopy_aware = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9654
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9655
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9656
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9657
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9658
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9659
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9660
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9661
	case IPPROTO_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9662
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9663
		case TCP_NODELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9664
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9665
				tcp->tcp_naglim = *i1 ? 1 : tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9666
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9667
		case TCP_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9668
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9669
				tcp->tcp_first_timer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9670
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9671
		case TCP_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9672
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9673
				tcp->tcp_second_timer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9674
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9675
		case TCP_CONN_NOTIFY_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9676
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9677
				tcp->tcp_first_ctimer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9678
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9679
		case TCP_CONN_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9680
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9681
				tcp->tcp_second_ctimer_threshold = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9682
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9683
		case TCP_RECVDSTADDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9684
			if (tcp->tcp_state > TCPS_LISTEN)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9685
				return (EOPNOTSUPP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9686
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9687
				tcp->tcp_recvdstaddr = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9688
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9689
		case TCP_ANONPRIVBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9690
			if ((reterr = secpolicy_net_privaddr(cr, 0)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9691
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9692
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9693
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9694
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9695
				tcp->tcp_anon_priv_bind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9696
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9697
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9698
		case TCP_EXCLBIND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9699
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9700
				tcp->tcp_exclbind = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9701
			break;	/* goto sizeof (int) option return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9702
		case TCP_INIT_CWND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9703
			uint32_t init_cwnd = *((uint32_t *)invalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9705
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9706
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9707
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9708
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9709
			 * Only allow socket with network configuration
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9710
			 * privilege to set the initial cwnd to be larger
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9711
			 * than allowed by RFC 3390.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9712
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9713
			if (init_cwnd <= MIN(4, MAX(2, 4380 / tcp->tcp_mss))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9714
				tcp->tcp_init_cwnd = init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9715
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9716
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9717
			if ((reterr = secpolicy_net_config(cr, B_TRUE)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9718
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9719
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9720
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9721
			if (init_cwnd > TCP_MAX_INIT_CWND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9722
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9723
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9724
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9725
			tcp->tcp_init_cwnd = init_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9726
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9727
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9728
		case TCP_KEEPALIVE_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9729
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9730
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9732
			if (*i1 < tcp_keepalive_interval_low ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9733
			    *i1 > tcp_keepalive_interval_high) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9734
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9735
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9736
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9737
			if (*i1 != tcp->tcp_ka_interval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9738
				tcp->tcp_ka_interval = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9739
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9740
				 * Check if we need to restart the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9741
				 * keepalive timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9742
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9743
				if (tcp->tcp_ka_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9744
					ASSERT(tcp->tcp_ka_enabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9745
					(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9746
					    tcp->tcp_ka_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9747
					tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9748
					tcp->tcp_ka_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9749
					    tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9750
					    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9751
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9752
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9753
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9754
		case TCP_KEEPALIVE_ABORT_THRESHOLD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9755
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9756
				if (*i1 < tcp_keepalive_abort_interval_low ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9757
				    *i1 > tcp_keepalive_abort_interval_high) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9758
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9759
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9760
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9761
				tcp->tcp_ka_abort_thres = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9762
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9763
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9764
		case TCP_CORK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9765
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9766
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9767
				 * if tcp->tcp_cork was set and is now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9768
				 * being unset, we have to make sure that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9769
				 * the remaining data gets sent out. Also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9770
				 * unset tcp->tcp_cork so that tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9771
				 * can send data even if it is less than mss
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9772
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9773
				if (tcp->tcp_cork && onoff == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9774
				    tcp->tcp_unsent > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9775
					tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9776
					tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9777
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9778
				tcp->tcp_cork = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9779
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9780
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9781
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9782
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9783
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9784
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9785
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9786
	case IPPROTO_IP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9787
		if (tcp->tcp_family != AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9788
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9789
			return (ENOPROTOOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9790
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9791
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9792
		case IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9793
		case T_IP_OPTIONS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9794
			reterr = tcp_opt_set_header(tcp, checkonly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9795
			    invalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9796
			if (reterr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9797
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9798
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9799
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9800
			/* OK return - copy input buffer into output buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9801
			if (invalp != outvalp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9802
				/* don't trust bcopy for identical src/dst */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9803
				bcopy(invalp, outvalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9804
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9805
			*outlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9806
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9807
		case IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9808
		case T_IP_TOS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9809
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9810
				tcp->tcp_ipha->ipha_type_of_service =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9811
				    (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9812
				tcp->tcp_tos = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9813
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9814
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9815
		case IP_TTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9816
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9817
				tcp->tcp_ipha->ipha_ttl = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9818
				tcp->tcp_ttl = (uchar_t)*i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9819
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9820
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9821
		case IP_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9822
			/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9823
			return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9824
		case IP_SEC_OPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9825
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9826
			 * We should not allow policy setting after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9827
			 * we start listening for connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9828
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9829
			if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9830
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9831
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9832
				/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9833
				return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9834
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9835
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9836
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9837
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9838
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9839
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9840
	case IPPROTO_IPV6: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9841
		ip6_pkt_t		*ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9843
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9844
		 * IPPROTO_IPV6 options are only supported for sockets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9845
		 * that are using IPv6 on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9846
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9847
		if (tcp->tcp_ipversion != IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9848
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9849
			return (ENOPROTOOPT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9850
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9851
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9852
		 * Only sticky options; no ancillary data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9853
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9854
		ASSERT(thisdg_attrs == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9855
		ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9857
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9858
		case IPV6_UNICAST_HOPS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9859
			/* -1 means use default */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9860
			if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9861
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9862
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9863
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9864
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9865
				if (*i1 == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9866
					tcp->tcp_ip6h->ip6_hops =
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9867
					    ipp->ipp_unicast_hops =
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9868
					    (uint8_t)tcp_ipv6_hoplimit;
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9869
					ipp->ipp_fields &= ~IPPF_UNICAST_HOPS;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9870
					/* Pass modified value to IP. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9871
					*i1 = tcp->tcp_ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9872
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9873
					tcp->tcp_ip6h->ip6_hops =
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9874
					    ipp->ipp_unicast_hops =
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9875
					    (uint8_t)*i1;
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9876
					ipp->ipp_fields |= IPPF_UNICAST_HOPS;
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9877
				}
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9878
				reterr = tcp_build_hdrs(q, tcp);
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9879
				if (reterr != 0)
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
  9880
					return (reterr);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9881
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9882
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9883
		case IPV6_BOUND_IF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9884
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9885
				int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9886
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9887
				tcp->tcp_bound_if = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9888
				error = ip_opt_set_ill(tcp->tcp_connp, *i1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9889
				    B_TRUE, checkonly, level, name, mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9890
				if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9891
					*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9892
					return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9893
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9894
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9895
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9896
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9897
		 * Set boolean switches for ancillary data delivery
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9898
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9899
		case IPV6_RECVPKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9900
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9901
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9902
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9903
					    TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9904
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9905
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9906
					    ~TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9907
				/* Force it to be sent up with the next msg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9908
				tcp->tcp_recvifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9909
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9910
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9911
		case IPV6_RECVTCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9912
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9913
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9914
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9915
					    TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9916
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9917
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9918
					    ~TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9919
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9920
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9921
		case IPV6_RECVHOPLIMIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9922
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9923
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9924
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9925
					    TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9926
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9927
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9928
					    ~TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9929
				/* Force it to be sent up with the next msg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9930
				tcp->tcp_recvhops = 0xffffffffU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9931
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9932
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9933
		case IPV6_RECVHOPOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9934
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9935
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9936
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9937
					    TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9938
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9939
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9940
					    ~TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9941
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9942
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9943
		case IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9944
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9945
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9946
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9947
					    TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9948
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9949
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9950
					    ~TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9951
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9952
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9953
		case _OLD_IPV6_RECVDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9954
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9955
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9956
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9957
					    TCP_OLD_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9958
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9959
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9960
					    ~TCP_OLD_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9961
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9962
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9963
		case IPV6_RECVRTHDR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9964
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9965
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9966
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9967
					    TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9968
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9969
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9970
					    ~TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9971
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9972
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9973
		case IPV6_RECVRTHDRDSTOPTS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9974
			if (!checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9975
				if (onoff)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9976
					tcp->tcp_ipv6_recvancillary |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9977
					    TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9978
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9979
					tcp->tcp_ipv6_recvancillary &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9980
					    ~TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9981
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9982
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9983
		case IPV6_PKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9984
			if (inlen != 0 && inlen != sizeof (struct in6_pktinfo))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9985
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9986
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9987
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9989
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9990
				ipp->ipp_fields &= ~(IPPF_IFINDEX|IPPF_ADDR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9991
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9992
				struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9994
				pkti = (struct in6_pktinfo *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9995
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9996
				 * RFC 3542 states that ipi6_addr must be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9997
				 * the unspecified address when setting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9998
				 * IPV6_PKTINFO sticky socket option on a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  9999
				 * TCP socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10000
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10001
				if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10002
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10003
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10004
				 * ip6_set_pktinfo() validates the source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10005
				 * address and interface index.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10006
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10007
				reterr = ip6_set_pktinfo(cr, tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10008
				    pkti, mblk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10009
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10010
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10011
				ipp->ipp_ifindex = pkti->ipi6_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10012
				ipp->ipp_addr = pkti->ipi6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10013
				if (ipp->ipp_ifindex != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10014
					ipp->ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10015
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10016
					ipp->ipp_fields &= ~IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10017
				if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10018
					ipp->ipp_fields |= IPPF_ADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10019
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10020
					ipp->ipp_fields &= ~IPPF_ADDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10021
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10022
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10023
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10024
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10025
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10026
		case IPV6_TCLASS:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10027
			if (inlen != 0 && inlen != sizeof (int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10028
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10029
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10030
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10032
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10033
				ipp->ipp_fields &= ~IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10034
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10035
				if (*i1 > 255 || *i1 < -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10036
					return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10037
				if (*i1 == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10038
					ipp->ipp_tclass = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10039
					*i1 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10040
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10041
					ipp->ipp_tclass = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10042
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10043
				ipp->ipp_fields |= IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10044
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10045
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10046
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10047
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10048
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10049
		case IPV6_NEXTHOP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10050
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10051
			 * IP will verify that the nexthop is reachable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10052
			 * and fail for sticky options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10053
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10054
			if (inlen != 0 && inlen != sizeof (sin6_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10055
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10056
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10057
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10059
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10060
				ipp->ipp_fields &= ~IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10061
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10062
				sin6_t *sin6 = (sin6_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10064
				if (sin6->sin6_family != AF_INET6)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10065
					return (EAFNOSUPPORT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10066
				if (IN6_IS_ADDR_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10067
				    &sin6->sin6_addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10068
					return (EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10069
				ipp->ipp_nexthop = sin6->sin6_addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10070
				if (!IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10071
				    &ipp->ipp_nexthop))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10072
					ipp->ipp_fields |= IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10073
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10074
					ipp->ipp_fields &= ~IPPF_NEXTHOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10075
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10076
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10077
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10078
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10079
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10080
		case IPV6_HOPOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10081
			ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10082
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10083
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10084
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10085
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10086
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10087
			    inlen != (8 * (hopts->ip6h_len + 1)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10088
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10090
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10091
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10092
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10093
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10094
				if ((ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10095
					kmem_free(ipp->ipp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10096
					    ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10097
					ipp->ipp_hopopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10098
					ipp->ipp_hopoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10099
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10100
				ipp->ipp_fields &= ~IPPF_HOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10101
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10102
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10103
				    (uchar_t **)&ipp->ipp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10104
				    &ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10105
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10106
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10107
				ipp->ipp_fields |= IPPF_HOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10108
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10109
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10110
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10111
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10112
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10113
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10114
		case IPV6_RTHDRDSTOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10115
			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10117
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10118
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10119
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10120
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10121
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10122
			    inlen != (8 * (dopts->ip6d_len + 1)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10123
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10125
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10126
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10128
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10129
				if ((ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10130
					kmem_free(ipp->ipp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10131
					    ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10132
					ipp->ipp_rtdstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10133
					ipp->ipp_rtdstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10134
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10135
				ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10136
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10137
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10138
				    (uchar_t **)&ipp->ipp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10139
				    &ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10140
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10141
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10142
				ipp->ipp_fields |= IPPF_RTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10143
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10144
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10145
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10146
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10147
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10148
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10149
		case IPV6_DSTOPTS: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10150
			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10152
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10153
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10154
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10155
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10156
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10157
			    inlen != (8 * (dopts->ip6d_len + 1)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10158
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10160
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10161
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10163
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10164
				if ((ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10165
					kmem_free(ipp->ipp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10166
					    ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10167
					ipp->ipp_dstopts = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10168
					ipp->ipp_dstoptslen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10169
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10170
				ipp->ipp_fields &= ~IPPF_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10171
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10172
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10173
				    (uchar_t **)&ipp->ipp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10174
				    &ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10175
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10176
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10177
				ipp->ipp_fields |= IPPF_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10178
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10179
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10180
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10181
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10182
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10183
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10184
		case IPV6_RTHDR: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10185
			ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10187
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10188
			 * Sanity checks - minimum size, size a multiple of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10189
			 * eight bytes, and matching size passed in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10190
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10191
			if (inlen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10192
			    inlen != (8 * (rt->ip6r_len + 1)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10193
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10195
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10196
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10197
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10198
			if (inlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10199
				if ((ipp->ipp_fields & IPPF_RTHDR) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10200
					kmem_free(ipp->ipp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10201
					    ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10202
					ipp->ipp_rthdr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10203
					ipp->ipp_rthdrlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10204
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10205
				ipp->ipp_fields &= ~IPPF_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10206
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10207
				reterr = tcp_pkt_set(invalp, inlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10208
				    (uchar_t **)&ipp->ipp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10209
				    &ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10210
				if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10211
					return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10212
				ipp->ipp_fields |= IPPF_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10213
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10214
			reterr = tcp_build_hdrs(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10215
			if (reterr != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10216
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10217
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10218
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10219
		case IPV6_V6ONLY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10220
			if (!checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10221
				tcp->tcp_connp->conn_ipv6_v6only = onoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10222
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10223
		case IPV6_USE_MIN_MTU:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10224
			if (inlen != sizeof (int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10225
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10227
			if (*i1 < -1 || *i1 > 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10228
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10230
			if (checkonly)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10231
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10233
			ipp->ipp_fields |= IPPF_USE_MIN_MTU;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10234
			ipp->ipp_use_min_mtu = *i1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10235
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10236
		case IPV6_BOUND_PIF:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10237
			/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10238
			return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10239
		case IPV6_SEC_OPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10240
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10241
			 * We should not allow policy setting after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10242
			 * we start listening for connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10243
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10244
			if (tcp->tcp_state == TCPS_LISTEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10245
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10246
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10247
				/* Handled at the IP level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10248
				return (-EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10249
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10250
		case IPV6_SRC_PREFERENCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10251
			if (inlen != sizeof (uint32_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10252
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10253
			reterr = ip6_set_src_preferences(tcp->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10254
			    *(uint32_t *)invalp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10255
			if (reterr != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10256
				*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10257
				return (reterr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10258
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10259
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10260
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10261
			*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10262
			return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10263
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10264
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10265
	}		/* end IPPROTO_IPV6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10266
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10267
		*outlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10268
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10269
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10270
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10271
	 * Common case of OK return with outval same as inval
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10272
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10273
	if (invalp != outvalp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10274
		/* don't trust bcopy for identical src/dst */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10275
		(void) bcopy(invalp, outvalp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10276
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10277
	*outlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10278
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10279
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10280
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10281
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10282
 * Update tcp_sticky_hdrs based on tcp_sticky_ipp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10283
 * The headers include ip6i_t (if needed), ip6_t, any sticky extension
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10284
 * headers, and the maximum size tcp header (to avoid reallocation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10285
 * on the fly for additional tcp options).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10286
 * Returns failure if can't allocate memory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10287
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10288
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10289
tcp_build_hdrs(queue_t *q, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10290
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10291
	char	*hdrs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10292
	uint_t	hdrs_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10293
	ip6i_t	*ip6i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10294
	char	buf[TCP_MAX_HDR_LENGTH];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10295
	ip6_pkt_t *ipp = &tcp->tcp_sticky_ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10296
	in6_addr_t src, dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10298
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10299
	 * save the existing tcp header and source/dest IP addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10300
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10301
	bcopy(tcp->tcp_tcph, buf, tcp->tcp_tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10302
	src = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10303
	dst = tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10304
	hdrs_len = ip_total_hdrs_len_v6(ipp) + TCP_MAX_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10305
	ASSERT(hdrs_len != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10306
	if (hdrs_len > tcp->tcp_iphc_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10307
		/* Need to reallocate */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10308
		hdrs = kmem_zalloc(hdrs_len, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10309
		if (hdrs == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10310
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10311
		if (tcp->tcp_iphc != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10312
			if (tcp->tcp_hdr_grown) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10313
				kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10314
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10315
				bzero(tcp->tcp_iphc, tcp->tcp_iphc_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10316
				kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10317
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10318
			tcp->tcp_iphc_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10319
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10320
		ASSERT(tcp->tcp_iphc_len == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10321
		tcp->tcp_iphc = hdrs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10322
		tcp->tcp_iphc_len = hdrs_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10323
		tcp->tcp_hdr_grown = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10324
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10325
	ip_build_hdrs_v6((uchar_t *)tcp->tcp_iphc,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10326
	    hdrs_len - TCP_MAX_HDR_LENGTH, ipp, IPPROTO_TCP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10328
	/* Set header fields not in ipp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10329
	if (ipp->ipp_fields & IPPF_HAS_IP6I) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10330
		ip6i = (ip6i_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10331
		tcp->tcp_ip6h = (ip6_t *)&ip6i[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10332
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10333
		tcp->tcp_ip6h = (ip6_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10334
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10335
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10336
	 * tcp->tcp_ip_hdr_len will include ip6i_t if there is one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10337
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10338
	 * tcp->tcp_tcp_hdr_len doesn't change here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10339
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10340
	tcp->tcp_ip_hdr_len = hdrs_len - TCP_MAX_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10341
	tcp->tcp_tcph = (tcph_t *)(tcp->tcp_iphc + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10342
	tcp->tcp_hdr_len = tcp->tcp_ip_hdr_len + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10344
	bcopy(buf, tcp->tcp_tcph, tcp->tcp_tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10346
	tcp->tcp_ip6h->ip6_src = src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10347
	tcp->tcp_ip6h->ip6_dst = dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10349
	/*
679
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10350
	 * If the hop limit was not set by ip_build_hdrs_v6(), set it to
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10351
	 * the default value for TCP.
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10352
	 */
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10353
	if (!(ipp->ipp_fields & IPPF_UNICAST_HOPS))
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10354
		tcp->tcp_ip6h->ip6_hops = tcp_ipv6_hoplimit;
f2c9450b58f4 6201425 setting IPV6_UNICAST_HOPS on SCTP socket doesn't do anything
seb
parents: 646
diff changeset
 10355
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10356
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10357
	 * If we're setting extension headers after a connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10358
	 * has been established, and if we have a routing header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10359
	 * among the extension headers, call ip_massage_options_v6 to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10360
	 * manipulate the routing header/ip6_dst set the checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10361
	 * difference in the tcp header template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10362
	 * (This happens in tcp_connect_ipv6 if the routing header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10363
	 * is set prior to the connect.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10364
	 * Set the tcp_sum to zero first in case we've cleared a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10365
	 * routing header or don't have one at all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10366
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10367
	tcp->tcp_sum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10368
	if ((tcp->tcp_state >= TCPS_SYN_SENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10369
	    (tcp->tcp_ipp_fields & IPPF_RTHDR)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10370
		ip6_rthdr_t *rth = ip_find_rthdr_v6(tcp->tcp_ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10371
		    (uint8_t *)tcp->tcp_tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10372
		if (rth != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10373
			tcp->tcp_sum = ip_massage_options_v6(tcp->tcp_ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10374
			    rth);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10375
			tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10376
			    (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10377
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10378
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10380
	/* Try to get everything in a single mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10381
	(void) mi_set_sth_wroff(RD(q), hdrs_len + tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10382
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10383
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10384
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10385
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10386
 * Set optbuf and optlen for the option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10387
 * Allocate memory (if not already present).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10388
 * Otherwise just point optbuf and optlen at invalp and inlen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10389
 * Returns failure if memory can not be allocated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10390
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10391
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10392
tcp_pkt_set(uchar_t *invalp, uint_t inlen, uchar_t **optbufp, uint_t *optlenp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10393
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10394
	uchar_t *optbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10396
	if (inlen == *optlenp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10397
		/* Unchanged length - no need to realocate */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10398
		bcopy(invalp, *optbufp, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10399
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10400
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10401
	if (inlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10402
		/* Allocate new buffer before free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10403
		optbuf = kmem_alloc(inlen, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10404
		if (optbuf == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10405
			return (ENOMEM);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10406
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10407
		optbuf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10409
	/* Free old buffer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10410
	if (*optlenp != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10411
		kmem_free(*optbufp, *optlenp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10412
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10413
	bcopy(invalp, optbuf, inlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10414
	*optbufp = optbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10415
	*optlenp = inlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10416
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10417
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10419
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10420
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10421
 * Use the outgoing IP header to create an IP_OPTIONS option the way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10422
 * it was passed down from the application.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10423
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10424
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10425
tcp_opt_get_user(ipha_t *ipha, uchar_t *buf)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10426
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10427
	ipoptp_t	opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10428
	uchar_t		*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10429
	uint8_t		optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10430
	uint8_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10431
	uint32_t	len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10432
	uchar_t	*buf1 = buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10434
	buf += IP_ADDR_LEN;	/* Leave room for final destination */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10435
	len += IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10436
	bzero(buf1, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10438
	for (optval = ipoptp_first(&opts, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10439
	    optval != IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10440
	    optval = ipoptp_next(&opts)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10441
		opt = opts.ipoptp_cur;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10442
		optlen = opts.ipoptp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10443
		switch (optval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10444
			int	off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10445
		case IPOPT_SSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10446
		case IPOPT_LSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10448
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10449
			 * Insert ipha_dst as the first entry in the source
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10450
			 * route and move down the entries on step.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10451
			 * The last entry gets placed at buf1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10452
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10453
			buf[IPOPT_OPTVAL] = optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10454
			buf[IPOPT_OLEN] = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10455
			buf[IPOPT_OFFSET] = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10457
			off = optlen - IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10458
			if (off < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10459
				/* No entries in source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10460
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10461
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10462
			/* Last entry in source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10463
			bcopy(opt + off, buf1, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10464
			off -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10466
			while (off > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10467
				bcopy(opt + off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10468
				    buf + off + IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10469
				    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10470
				off -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10471
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10472
			/* ipha_dst into first slot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10473
			bcopy(&ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10474
			    buf + off + IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10475
			    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10476
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10477
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10478
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10479
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10480
			bcopy(opt, buf, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10481
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10482
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10483
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10484
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10485
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10486
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10487
	/* Pad the resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10488
	while (len & 0x3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10489
		*buf++ = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10490
		len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10491
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10492
	return (len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10493
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10495
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10496
 * Transfer any source route option from ipha to buf/dst in reversed form.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10497
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10498
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10499
tcp_opt_rev_src_route(ipha_t *ipha, char *buf, uchar_t *dst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10500
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10501
	ipoptp_t	opts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10502
	uchar_t		*opt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10503
	uint8_t		optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10504
	uint8_t		optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10505
	uint32_t	len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10507
	for (optval = ipoptp_first(&opts, ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10508
	    optval != IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10509
	    optval = ipoptp_next(&opts)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10510
		opt = opts.ipoptp_cur;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10511
		optlen = opts.ipoptp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10512
		switch (optval) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10513
			int	off1, off2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10514
		case IPOPT_SSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10515
		case IPOPT_LSRR:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10516
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10517
			/* Reverse source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10518
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10519
			 * First entry should be the next to last one in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10520
			 * current source route (the last entry is our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10521
			 * address.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10522
			 * The last entry should be the final destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10523
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10524
			buf[IPOPT_OPTVAL] = (uint8_t)optval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10525
			buf[IPOPT_OLEN] = (uint8_t)optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10526
			off1 = IPOPT_MINOFF_SR - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10527
			off2 = opt[IPOPT_OFFSET] - IP_ADDR_LEN - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10528
			if (off2 < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10529
				/* No entries in source route */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10530
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10531
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10532
			bcopy(opt + off2, dst, IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10533
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10534
			 * Note: use src since ipha has not had its src
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10535
			 * and dst reversed (it is in the state it was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10536
			 * received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10537
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10538
			bcopy(&ipha->ipha_src, buf + off2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10539
			    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10540
			off2 -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10542
			while (off2 > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10543
				bcopy(opt + off2, buf + off1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10544
				    IP_ADDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10545
				off1 += IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10546
				off2 -= IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10547
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10548
			buf[IPOPT_OFFSET] = IPOPT_MINOFF_SR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10549
			buf += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10550
			len += optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10551
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10552
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10553
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10554
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10555
	/* Pad the resulting options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10556
	while (len & 0x3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10557
		*buf++ = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10558
		len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10559
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10560
	return (len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10561
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10564
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10565
 * Extract and revert a source route from ipha (if any)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10566
 * and then update the relevant fields in both tcp_t and the standard header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10567
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10568
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10569
tcp_opt_reverse(tcp_t *tcp, ipha_t *ipha)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10570
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10571
	char	buf[TCP_MAX_HDR_LENGTH];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10572
	uint_t	tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10573
	int	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10574
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10575
	ASSERT(IPH_HDR_VERSION(ipha) == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10576
	len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10577
	if (len == IP_SIMPLE_HDR_LENGTH)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10578
		/* Nothing to do */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10579
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10580
	if (len > IP_SIMPLE_HDR_LENGTH + TCP_MAX_IP_OPTIONS_LENGTH ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10581
	    (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10582
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10584
	tcph_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10585
	bcopy(tcp->tcp_tcph, buf, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10586
	tcp->tcp_sum = (tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10587
		(tcp->tcp_ipha->ipha_dst & 0xffff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10588
	len = tcp_opt_rev_src_route(ipha, (char *)tcp->tcp_ipha +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10589
	    IP_SIMPLE_HDR_LENGTH, (uchar_t *)&tcp->tcp_ipha->ipha_dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10590
	len += IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10591
	tcp->tcp_sum -= ((tcp->tcp_ipha->ipha_dst >> 16) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10592
	    (tcp->tcp_ipha->ipha_dst & 0xffff));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10593
	if ((int)tcp->tcp_sum < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10594
		tcp->tcp_sum--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10595
	tcp->tcp_sum = (tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10596
	tcp->tcp_sum = ntohs((tcp->tcp_sum & 0xFFFF) + (tcp->tcp_sum >> 16));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10597
	tcp->tcp_tcph = (tcph_t *)((char *)tcp->tcp_ipha + len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10598
	bcopy(buf, tcp->tcp_tcph, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10599
	tcp->tcp_ip_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10600
	tcp->tcp_ipha->ipha_version_and_hdr_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10601
	    (IP_VERSION << 4) | (len >> 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10602
	len += tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10603
	tcp->tcp_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10604
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10605
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10606
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10607
 * Copy the standard header into its new location,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10608
 * lay in the new options and then update the relevant
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10609
 * fields in both tcp_t and the standard header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10610
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10611
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10612
tcp_opt_set_header(tcp_t *tcp, boolean_t checkonly, uchar_t *ptr, uint_t len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10613
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10614
	uint_t	tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10615
	char	*ip_optp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10616
	tcph_t	*new_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10618
	if (checkonly) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10619
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10620
		 * do not really set, just pretend to - T_CHECK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10621
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10622
		if (len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10623
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10624
			 * there is value supplied, validate it as if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10625
			 * for a real set operation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10626
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10627
			if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10628
				return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10629
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10630
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10631
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10632
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10633
	if ((len > TCP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10634
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10635
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10636
	ip_optp = (char *)tcp->tcp_ipha + IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10637
	tcph_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10638
	new_tcph = (tcph_t *)(ip_optp + len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10639
	ovbcopy((char *)tcp->tcp_tcph, (char *)new_tcph, tcph_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10640
	tcp->tcp_tcph = new_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10641
	bcopy(ptr, ip_optp, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10642
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10643
	len += IP_SIMPLE_HDR_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10644
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10645
	tcp->tcp_ip_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10646
	tcp->tcp_ipha->ipha_version_and_hdr_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10647
		(IP_VERSION << 4) | (len >> 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10648
	len += tcph_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10649
	tcp->tcp_hdr_len = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10650
	if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10651
		/* Always allocate room for all options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10652
		(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10653
		    TCP_MAX_COMBINED_HEADER_LENGTH + tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10654
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10655
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10656
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10658
/* Get callback routine passed to nd_load by tcp_param_register */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10659
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10660
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10661
tcp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10662
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10663
	tcpparam_t	*tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10664
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10665
	(void) mi_mpprintf(mp, "%u", tcppa->tcp_param_val);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10666
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10667
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10669
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10670
 * Walk through the param array specified registering each element with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10671
 * named dispatch handler.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10672
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10673
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10674
tcp_param_register(tcpparam_t *tcppa, int cnt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10675
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10676
	for (; cnt-- > 0; tcppa++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10677
		if (tcppa->tcp_param_name && tcppa->tcp_param_name[0]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10678
			if (!nd_load(&tcp_g_nd, tcppa->tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10679
			    tcp_param_get, tcp_param_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10680
			    (caddr_t)tcppa)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10681
				nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10682
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10683
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10684
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10685
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10686
	if (!nd_load(&tcp_g_nd, tcp_wroff_xtra_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10687
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10688
	    (caddr_t)&tcp_wroff_xtra_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10689
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10690
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10691
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10692
	if (!nd_load(&tcp_g_nd, tcp_mdt_head_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10693
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10694
	    (caddr_t)&tcp_mdt_head_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10695
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10696
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10697
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10698
	if (!nd_load(&tcp_g_nd, tcp_mdt_tail_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10699
	    tcp_param_get, tcp_param_set_aligned,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10700
	    (caddr_t)&tcp_mdt_tail_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10701
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10702
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10704
	if (!nd_load(&tcp_g_nd, tcp_mdt_max_pbufs_param.tcp_param_name,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10705
	    tcp_param_get, tcp_param_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10706
	    (caddr_t)&tcp_mdt_max_pbufs_param)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10707
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10708
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10709
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10710
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10711
	    tcp_extra_priv_ports_get, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10712
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10713
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10714
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10715
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports_add",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10716
	    NULL, tcp_extra_priv_ports_add, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10717
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10718
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10719
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10720
	if (!nd_load(&tcp_g_nd, "tcp_extra_priv_ports_del",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10721
	    NULL, tcp_extra_priv_ports_del, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10722
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10723
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10724
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10725
	if (!nd_load(&tcp_g_nd, "tcp_status", tcp_status_report, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10726
	    NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10727
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10728
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10729
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10730
	if (!nd_load(&tcp_g_nd, "tcp_bind_hash", tcp_bind_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10731
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10732
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10733
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10734
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10735
	if (!nd_load(&tcp_g_nd, "tcp_listen_hash", tcp_listen_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10736
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10737
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10738
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10739
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10740
	if (!nd_load(&tcp_g_nd, "tcp_conn_hash", tcp_conn_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10741
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10742
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10743
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10744
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10745
	if (!nd_load(&tcp_g_nd, "tcp_acceptor_hash", tcp_acceptor_hash_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10746
	    NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10747
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10748
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10749
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10750
	if (!nd_load(&tcp_g_nd, "tcp_host_param", tcp_host_param_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10751
	    tcp_host_param_set, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10752
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10753
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10754
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10755
	if (!nd_load(&tcp_g_nd, "tcp_host_param_ipv6", tcp_host_param_report,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10756
	    tcp_host_param_set_ipv6, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10757
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10758
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10759
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10760
	if (!nd_load(&tcp_g_nd, "tcp_1948_phrase", NULL, tcp_1948_phrase_set,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10761
	    NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10762
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10763
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10764
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10765
	if (!nd_load(&tcp_g_nd, "tcp_reserved_port_list",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10766
	    tcp_reserved_port_list, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10767
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10768
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10769
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10770
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10771
	 * Dummy ndd variables - only to convey obsolescence information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10772
	 * through printing of their name (no get or set routines)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10773
	 * XXX Remove in future releases ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10774
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10775
	if (!nd_load(&tcp_g_nd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10776
	    "tcp_close_wait_interval(obsoleted - "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10777
	    "use tcp_time_wait_interval)", NULL, NULL, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10778
		nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10779
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10780
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10781
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10782
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10784
/* ndd set routine for tcp_wroff_xtra, tcp_mdt_hdr_{head,tail}_min. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10785
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10786
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10787
tcp_param_set_aligned(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10788
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10789
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10790
	long new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10791
	tcpparam_t *tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10792
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10793
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10794
	    new_value < tcppa->tcp_param_min ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10795
	    new_value > tcppa->tcp_param_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10796
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10797
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10798
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10799
	 * Need to make sure new_value is a multiple of 4.  If it is not,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10800
	 * round it up.  For future 64 bit requirement, we actually make it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10801
	 * a multiple of 8.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10802
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10803
	if (new_value & 0x7) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10804
		new_value = (new_value & ~0x7) + 0x8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10805
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10806
	tcppa->tcp_param_val = new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10807
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10808
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10810
/* Set callback routine passed to nd_load by tcp_param_register */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10811
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10812
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10813
tcp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10814
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10815
	long	new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10816
	tcpparam_t	*tcppa = (tcpparam_t *)cp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10818
	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10819
	    new_value < tcppa->tcp_param_min ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10820
	    new_value > tcppa->tcp_param_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10821
		return (EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10822
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10823
	tcppa->tcp_param_val = new_value;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10824
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10825
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10827
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10828
 * Add a new piece to the tcp reassembly queue.  If the gap at the beginning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10829
 * is filled, return as much as we can.  The message passed in may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10830
 * multi-part, chained using b_cont.  "start" is the starting sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10831
 * number for this piece.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10832
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10833
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10834
tcp_reass(tcp_t *tcp, mblk_t *mp, uint32_t start)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10835
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10836
	uint32_t	end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10837
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10838
	mblk_t		*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10839
	mblk_t		*next_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10840
	uint32_t	u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10842
	/* Walk through all the new pieces. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10843
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10844
		ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10845
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10846
		end = start + (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10847
		next_mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10848
		if (start == end) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10849
			/* Empty.  Blast it. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10850
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10851
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10852
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10853
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10854
		TCP_REASS_SET_SEQ(mp, start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10855
		TCP_REASS_SET_END(mp, end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10856
		mp1 = tcp->tcp_reass_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10857
		if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10858
			tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10859
			tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10860
			BUMP_MIB(&tcp_mib, tcpInDataUnorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10861
			UPDATE_MIB(&tcp_mib,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10862
			    tcpInDataUnorderBytes, end - start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10863
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10864
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10865
		/* New stuff completely beyond tail? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10866
		if (SEQ_GEQ(start, TCP_REASS_END(mp1))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10867
			/* Link it on end. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10868
			mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10869
			tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10870
			BUMP_MIB(&tcp_mib, tcpInDataUnorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10871
			UPDATE_MIB(&tcp_mib,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10872
			    tcpInDataUnorderBytes, end - start);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10873
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10874
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10875
		mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10876
		u1 = TCP_REASS_SEQ(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10877
		/* New stuff at the front? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10878
		if (SEQ_LT(start, u1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10879
			/* Yes... Check for overlap. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10880
			mp->b_cont = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10881
			tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10882
			tcp_reass_elim_overlap(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10883
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10884
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10885
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10886
		 * The new piece fits somewhere between the head and tail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10887
		 * We find our slot, where mp1 precedes us and mp2 trails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10888
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10889
		for (; (mp2 = mp1->b_cont) != NULL; mp1 = mp2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10890
			u1 = TCP_REASS_SEQ(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10891
			if (SEQ_LEQ(start, u1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10892
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10893
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10894
		/* Link ourselves in */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10895
		mp->b_cont = mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10896
		mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10897
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10898
		/* Trim overlap with following mblk(s) first */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10899
		tcp_reass_elim_overlap(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10901
		/* Trim overlap with preceding mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10902
		tcp_reass_elim_overlap(tcp, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10904
	} while (start = end, mp = next_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10905
	mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10906
	/* Anything ready to go? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10907
	if (TCP_REASS_SEQ(mp1) != tcp->tcp_rnxt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10908
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10909
	/* Eat what we can off the queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10910
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10911
		mp = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10912
		end = TCP_REASS_END(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10913
		TCP_REASS_SET_SEQ(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10914
		TCP_REASS_SET_END(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10915
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10916
			tcp->tcp_reass_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10917
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10918
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10919
		if (end != TCP_REASS_SEQ(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10920
			mp1->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10921
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10922
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10923
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10924
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10925
	mp1 = tcp->tcp_reass_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10926
	tcp->tcp_reass_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10927
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10928
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10930
/* Eliminate any overlap that mp may have over later mblks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10931
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10932
tcp_reass_elim_overlap(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10933
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10934
	uint32_t	end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10935
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10936
	uint32_t	u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10937
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10938
	end = TCP_REASS_END(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10939
	while ((mp1 = mp->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10940
		u1 = TCP_REASS_SEQ(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10941
		if (!SEQ_GT(end, u1))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10942
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10943
		if (!SEQ_GEQ(end, TCP_REASS_END(mp1))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10944
			mp->b_wptr -= end - u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10945
			TCP_REASS_SET_END(mp, u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10946
			BUMP_MIB(&tcp_mib, tcpInDataPartDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10947
			UPDATE_MIB(&tcp_mib, tcpInDataPartDupBytes, end - u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10948
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10949
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10950
		mp->b_cont = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10951
		TCP_REASS_SET_SEQ(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10952
		TCP_REASS_SET_END(mp1, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10953
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10954
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10955
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes, end - u1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10956
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10957
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10958
		tcp->tcp_reass_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10959
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10961
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10962
 * Send up all messages queued on tcp_rcv_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10963
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10964
static uint_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10965
tcp_rcv_drain(queue_t *q, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10966
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10967
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10968
	uint_t ret = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10969
	uint_t thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10970
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10971
	uint_t cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10972
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10973
	/* Can't drain on an eager connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10974
	if (tcp->tcp_listener != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10975
		return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10976
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10977
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10978
	 * Handle two cases here: we are currently fused or we were
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10979
	 * previously fused and have some urgent data to be delivered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10980
	 * upstream.  The latter happens because we either ran out of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10981
	 * memory or were detached and therefore sending the SIGURG was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10982
	 * deferred until this point.  In either case we pass control
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10983
	 * over to tcp_fuse_rcv_drain() since it may need to complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10984
	 * some work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10985
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10986
	if ((tcp->tcp_fused || tcp->tcp_fused_sigurg)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10987
		ASSERT(tcp->tcp_fused_sigurg_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10988
		if (tcp_fuse_rcv_drain(q, tcp, tcp->tcp_fused ? NULL :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10989
		    &tcp->tcp_fused_sigurg_mp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10990
			return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10991
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10993
	while ((mp = tcp->tcp_rcv_list) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10994
		tcp->tcp_rcv_list = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10995
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10996
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10997
		cnt += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10998
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 10999
		putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11000
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11001
	ASSERT(cnt == tcp->tcp_rcv_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11002
	tcp->tcp_rcv_last_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11003
	tcp->tcp_rcv_last_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11004
	tcp->tcp_rcv_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11006
	/* Learn the latest rwnd information that we sent to the other side. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11007
	thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11008
	    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11009
	/* This is peer's calculated send window (our receive window). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11010
	thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11011
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11012
	 * Increase the receive window to max.  But we need to do receiver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11013
	 * SWS avoidance.  This means that we need to check the increase of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11014
	 * of receive window is at least 1 MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11015
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11016
	if (canputnext(q) && (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11017
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11018
		 * If the window that the other side knows is less than max
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11019
		 * deferred acks segments, send an update immediately.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11020
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11021
		if (thwin < tcp->tcp_rack_cur_max * tcp->tcp_mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11022
			BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11023
			ret = TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11024
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11025
		tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11026
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11027
	/* No need for the push timer now. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11028
	if (tcp->tcp_push_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11029
		(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_push_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11030
		tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11031
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11032
	return (ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11033
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11035
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11036
 * Queue data on tcp_rcv_list which is a b_next chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11037
 * tcp_rcv_last_head/tail is the last element of this chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11038
 * Each element of the chain is a b_cont chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11039
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11040
 * M_DATA messages are added to the current element.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11041
 * Other messages are added as new (b_next) elements.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11042
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 11043
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11044
tcp_rcv_enqueue(tcp_t *tcp, mblk_t *mp, uint_t seg_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11045
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11046
	ASSERT(seg_len == msgdsize(mp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11047
	ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_rcv_last_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11048
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11049
	if (tcp->tcp_rcv_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11050
		ASSERT(tcp->tcp_rcv_last_head == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11051
		tcp->tcp_rcv_list = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11052
		tcp->tcp_rcv_last_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11053
	} else if (DB_TYPE(mp) == DB_TYPE(tcp->tcp_rcv_last_head)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11054
		tcp->tcp_rcv_last_tail->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11055
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11056
		tcp->tcp_rcv_last_head->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11057
		tcp->tcp_rcv_last_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11058
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11060
	while (mp->b_cont)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11061
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11062
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11063
	tcp->tcp_rcv_last_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11064
	tcp->tcp_rcv_cnt += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11065
	tcp->tcp_rwnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11066
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11067
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11068
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11069
 * DEFAULT TCP ENTRY POINT via squeue on READ side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11070
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11071
 * This is the default entry function into TCP on the read side. TCP is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11072
 * always entered via squeue i.e. using squeue's for mutual exclusion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11073
 * When classifier does a lookup to find the tcp, it also puts a reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11074
 * on the conn structure associated so the tcp is guaranteed to exist
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11075
 * when we come here. We still need to check the state because it might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11076
 * as well has been closed. The squeue processing function i.e. squeue_enter,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11077
 * squeue_enter_nodrain, or squeue_drain is responsible for doing the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11078
 * CONN_DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11079
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11080
 * Apart from the default entry point, IP also sends packets directly to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11081
 * tcp_rput_data for AF_INET fast path and tcp_conn_request for incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11082
 * connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11083
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11084
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11085
tcp_input(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11086
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11087
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11088
	tcp_t	*tcp = (tcp_t *)connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11089
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11090
	/* arg2 is the sqp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11091
	ASSERT(arg2 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11092
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11094
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11095
	 * Don't accept any input on a closed tcp as this TCP logically does
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11096
	 * not exist on the system. Don't proceed further with this TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11097
	 * For eg. this packet could trigger another close of this tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11098
	 * which would be disastrous for tcp_refcnt. tcp_close_detached /
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11099
	 * tcp_clean_death / tcp_closei_local must be called at most once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11100
	 * on a TCP. In this case we need to refeed the packet into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11101
	 * classifier and figure out where the packet should go. Need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11102
	 * preserve the recv_ill somehow. Until we figure that out, for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11103
	 * now just drop the packet if we can't classify the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11104
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11105
	if (tcp->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11106
	    tcp->tcp_state == TCPS_BOUND) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11107
		conn_t	*new_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11109
		new_connp = ipcl_classify(mp, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11110
		if (new_connp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11111
			tcp_reinput(new_connp, mp, arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11112
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11113
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11114
		/* We failed to classify. For now just drop the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11115
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11116
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11117
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11119
	if (DB_TYPE(mp) == M_DATA)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11120
		tcp_rput_data(connp, mp, arg2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11121
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11122
		tcp_rput_common(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11123
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11125
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11126
 * The read side put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11127
 * The packets passed up by ip are assume to be aligned according to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11128
 * OK_32PTR and the IP+TCP headers fitting in the first mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11129
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11130
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11131
tcp_rput_common(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11132
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11133
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11134
	 * tcp_rput_data() does not expect M_CTL except for the case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11135
	 * where tcp_ipv6_recvancillary is set and we get a IN_PKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11136
	 * type. Need to make sure that any other M_CTLs don't make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11137
	 * it to tcp_rput_data since it is not expecting any and doesn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11138
	 * check for it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11139
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11140
	if (DB_TYPE(mp) == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11141
		switch (*(uint32_t *)(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11142
		case TCP_IOC_ABORT_CONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11143
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11144
			 * Handle connection abort request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11145
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11146
			tcp_ioctl_abort_handler(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11147
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11148
		case IPSEC_IN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11149
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11150
			 * Only secure icmp arrive in TCP and they
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11151
			 * don't go through data path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11152
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11153
			tcp_icmp_error(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11154
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11155
		case IN_PKTINFO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11156
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11157
			 * Handle IPV6_RECVPKTINFO socket option on AF_INET6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11158
			 * sockets that are receiving IPv4 traffic. tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11159
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11160
			ASSERT(tcp->tcp_family == AF_INET6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11161
			ASSERT(tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11162
			    TCP_IPV6_RECVPKTINFO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11163
			tcp_rput_data(tcp->tcp_connp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11164
			    tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11165
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11166
		case MDT_IOC_INFO_UPDATE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11167
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11168
			 * Handle Multidata information update; the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11169
			 * following routine will free the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11170
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11171
			if (tcp->tcp_connp->conn_mdt_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11172
				tcp_mdt_update(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11173
				    &((ip_mdt_info_t *)mp->b_rptr)->mdt_capab,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11174
				    B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11175
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11176
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11177
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11178
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11179
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11180
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11181
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11183
	/* No point processing the message if tcp is already closed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11184
	if (TCP_IS_DETACHED_NONEAGER(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11185
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11186
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11187
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11189
	tcp_rput_other(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11190
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11193
/* The minimum of smoothed mean deviation in RTO calculation. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11194
#define	TCP_SD_MIN	400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11196
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11197
 * Set RTO for this connection.  The formula is from Jacobson and Karels'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11198
 * "Congestion Avoidance and Control" in SIGCOMM '88.  The variable names
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11199
 * are the same as those in Appendix A.2 of that paper.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11200
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11201
 * m = new measurement
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11202
 * sa = smoothed RTT average (8 * average estimates).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11203
 * sv = smoothed mean deviation (mdev) of RTT (4 * deviation estimates).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11204
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11205
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11206
tcp_set_rto(tcp_t *tcp, clock_t rtt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11207
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11208
	long m = TICK_TO_MSEC(rtt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11209
	clock_t sa = tcp->tcp_rtt_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11210
	clock_t sv = tcp->tcp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11211
	clock_t rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11213
	BUMP_MIB(&tcp_mib, tcpRttUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11214
	tcp->tcp_rtt_update++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11216
	/* tcp_rtt_sa is not 0 means this is a new sample. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11217
	if (sa != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11218
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11219
		 * Update average estimator:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11220
		 *	new rtt = 7/8 old rtt + 1/8 Error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11221
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11223
		/* m is now Error in estimate. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11224
		m -= sa >> 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11225
		if ((sa += m) <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11226
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11227
			 * Don't allow the smoothed average to be negative.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11228
			 * We use 0 to denote reinitialization of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11229
			 * variables.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11230
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11231
			sa = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11232
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11233
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11234
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11235
		 * Update deviation estimator:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11236
		 *	new mdev = 3/4 old mdev + 1/4 (abs(Error) - old mdev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11237
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11238
		if (m < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11239
			m = -m;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11240
		m -= sv >> 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11241
		sv += m;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11242
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11243
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11244
		 * This follows BSD's implementation.  So the reinitialized
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11245
		 * RTO is 3 * m.  We cannot go less than 2 because if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11246
		 * link is bandwidth dominated, doubling the window size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11247
		 * during slow start means doubling the RTT.  We want to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11248
		 * more conservative when we reinitialize our estimates.  3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11249
		 * is just a convenient number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11250
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11251
		sa = m << 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11252
		sv = m << 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11253
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11254
	if (sv < TCP_SD_MIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11255
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11256
		 * We do not know that if sa captures the delay ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11257
		 * effect as in a long train of segments, a receiver
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11258
		 * does not delay its ACKs.  So set the minimum of sv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11259
		 * to be TCP_SD_MIN, which is default to 400 ms, twice
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11260
		 * of BSD DATO.  That means the minimum of mean
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11261
		 * deviation is 100 ms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11262
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11263
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11264
		sv = TCP_SD_MIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11265
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11266
	tcp->tcp_rtt_sa = sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11267
	tcp->tcp_rtt_sd = sv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11268
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11269
	 * RTO = average estimates (sa / 8) + 4 * deviation estimates (sv)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11270
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11271
	 * Add tcp_rexmit_interval extra in case of extreme environment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11272
	 * where the algorithm fails to work.  The default value of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11273
	 * tcp_rexmit_interval_extra should be 0.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11274
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11275
	 * As we use a finer grained clock than BSD and update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11276
	 * RTO for every ACKs, add in another .25 of RTT to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11277
	 * deviation of RTO to accomodate burstiness of 1/4 of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11278
	 * window size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11279
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11280
	rto = (sa >> 3) + sv + tcp_rexmit_interval_extra + (sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11281
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11282
	if (rto > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11283
		tcp->tcp_rto = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11284
	} else if (rto < tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11285
		tcp->tcp_rto = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11286
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11287
		tcp->tcp_rto = rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11288
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11290
	/* Now, we can reset tcp_timer_backoff to use the new RTO... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11291
	tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11292
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11294
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11295
 * tcp_get_seg_mp() is called to get the pointer to a segment in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11296
 * send queue which starts at the given seq. no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11297
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11298
 * Parameters:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11299
 *	tcp_t *tcp: the tcp instance pointer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11300
 *	uint32_t seq: the starting seq. no of the requested segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11301
 *	int32_t *off: after the execution, *off will be the offset to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11302
 *		the returned mblk which points to the requested seq no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11303
 *		It is the caller's responsibility to send in a non-null off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11304
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11305
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11306
 *	A mblk_t pointer pointing to the requested segment in send queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11307
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11308
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11309
tcp_get_seg_mp(tcp_t *tcp, uint32_t seq, int32_t *off)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11310
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11311
	int32_t	cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11312
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11314
	/* Defensive coding.  Make sure we don't send incorrect data. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11315
	if (SEQ_LT(seq, tcp->tcp_suna) || SEQ_GEQ(seq, tcp->tcp_snxt))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11316
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11318
	cnt = seq - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11319
	mp = tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11320
	while (cnt > 0 && mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11321
		cnt -= mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11322
		if (cnt < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11323
			cnt += mp->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11324
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11325
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11326
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11327
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11328
	ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11329
	*off = cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11330
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11331
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11333
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11334
 * This function handles all retransmissions if SACK is enabled for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11335
 * connection.  First it calculates how many segments can be retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11336
 * based on tcp_pipe.  Then it goes thru the notsack list to find eligible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11337
 * segments.  A segment is eligible if sack_cnt for that segment is greater
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11338
 * than or equal tcp_dupack_fast_retransmit.  After it has retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11339
 * all eligible segments, it checks to see if TCP can send some new segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11340
 * (fast recovery).  If it can, set the appropriate flag for tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11341
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11342
 * Parameters:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11343
 *	tcp_t *tcp: the tcp structure of the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11344
 *	uint_t *flags: in return, appropriate value will be set for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11345
 *	tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11346
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11347
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11348
tcp_sack_rxmit(tcp_t *tcp, uint_t *flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11349
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11350
	notsack_blk_t	*notsack_blk;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11351
	int32_t		usable_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11352
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11353
	uint32_t	seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11354
	mblk_t		*xmit_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11356
	ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11357
	ASSERT(tcp->tcp_notsack_list != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11358
	ASSERT(tcp->tcp_rexmit == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11359
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11360
	/* Defensive coding in case there is a bug... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11361
	if (tcp->tcp_notsack_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11362
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11364
	notsack_blk = tcp->tcp_notsack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11365
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11367
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11368
	 * Limit the num of outstanding data in the network to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11369
	 * tcp_cwnd_ssthresh, which is half of the original congestion wnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11370
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11371
	usable_swnd = tcp->tcp_cwnd_ssthresh - tcp->tcp_pipe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11372
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11373
	/* At least retransmit 1 MSS of data. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11374
	if (usable_swnd <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11375
		usable_swnd = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11376
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11378
	/* Make sure no new RTT samples will be taken. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11379
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11381
	notsack_blk = tcp->tcp_notsack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11382
	while (usable_swnd > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11383
		mblk_t		*snxt_mp, *tmp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11384
		tcp_seq		begin = tcp->tcp_sack_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11385
		tcp_seq		end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11386
		int32_t		off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11388
		for (; notsack_blk != NULL; notsack_blk = notsack_blk->next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11389
			if (SEQ_GT(notsack_blk->end, begin) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11390
			    (notsack_blk->sack_cnt >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11391
			    tcp_dupack_fast_retransmit)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11392
				end = notsack_blk->end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11393
				if (SEQ_LT(begin, notsack_blk->begin)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11394
					begin = notsack_blk->begin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11395
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11396
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11397
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11398
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11399
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11400
		 * All holes are filled.  Manipulate tcp_cwnd to send more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11401
		 * if we can.  Note that after the SACK recovery, tcp_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11402
		 * set to tcp_cwnd_ssthresh.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11403
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11404
		if (notsack_blk == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11405
			usable_swnd = tcp->tcp_cwnd_ssthresh - tcp->tcp_pipe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11406
			if (usable_swnd <= 0 || tcp->tcp_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11407
				tcp->tcp_cwnd = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11408
				ASSERT(tcp->tcp_cwnd > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11409
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11410
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11411
				usable_swnd = usable_swnd / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11412
				tcp->tcp_cwnd = tcp->tcp_snxt - tcp->tcp_suna +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11413
				    MAX(usable_swnd * mss, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11414
				*flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11415
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11416
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11417
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11419
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11420
		 * Note that we may send more than usable_swnd allows here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11421
		 * because of round off, but no more than 1 MSS of data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11422
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11423
		seg_len = end - begin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11424
		if (seg_len > mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11425
			seg_len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11426
		snxt_mp = tcp_get_seg_mp(tcp, begin, &off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11427
		ASSERT(snxt_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11428
		/* This should not happen.  Defensive coding again... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11429
		if (snxt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11430
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11431
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11433
		xmit_mp = tcp_xmit_mp(tcp, snxt_mp, seg_len, &off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11434
		    &tmp_mp, begin, B_TRUE, &seg_len, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11435
		if (xmit_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11436
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11438
		usable_swnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11439
		tcp->tcp_pipe += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11440
		tcp->tcp_sack_snxt = begin + seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11441
		TCP_RECORD_TRACE(tcp, xmit_mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11442
		tcp_send_data(tcp, tcp->tcp_wq, xmit_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11443
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11444
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11445
		 * Update the send timestamp to avoid false retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11446
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11447
		snxt_mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11449
		BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11450
		UPDATE_MIB(&tcp_mib, tcpRetransBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11451
		BUMP_MIB(&tcp_mib, tcpOutSackRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11452
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11453
		 * Update tcp_rexmit_max to extend this SACK recovery phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11454
		 * This happens when new data sent during fast recovery is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11455
		 * also lost.  If TCP retransmits those new data, it needs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11456
		 * to extend SACK recover phase to avoid starting another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11457
		 * fast retransmit/recovery unnecessarily.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11458
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11459
		if (SEQ_GT(tcp->tcp_sack_snxt, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11460
			tcp->tcp_rexmit_max = tcp->tcp_sack_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11461
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11462
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11463
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11465
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11466
 * This function handles policy checking at TCP level for non-hard_bound/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11467
 * detached connections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11468
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11469
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11470
tcp_check_policy(tcp_t *tcp, mblk_t *first_mp, ipha_t *ipha, ip6_t *ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11471
    boolean_t secure, boolean_t mctl_present)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11472
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11473
	ipsec_latch_t *ipl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11474
	ipsec_action_t *act = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11475
	mblk_t *data_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11476
	ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11477
	const char *reason;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11478
	kstat_named_t *counter;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11479
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11480
	ASSERT(mctl_present || !secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11482
	ASSERT((ipha == NULL && ip6h != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11483
	    (ip6h == NULL && ipha != NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11485
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11486
	 * We don't necessarily have an ipsec_in_act action to verify
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11487
	 * policy because of assymetrical policy where we have only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11488
	 * outbound policy and no inbound policy (possible with global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11489
	 * policy).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11490
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11491
	if (!secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11492
		if (act == NULL || act->ipa_act.ipa_type == IPSEC_ACT_BYPASS ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11493
		    act->ipa_act.ipa_type == IPSEC_ACT_CLEAR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11494
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11495
		ipsec_log_policy_failure(tcp->tcp_wq, IPSEC_POLICY_MISMATCH,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11496
		    "tcp_check_policy", ipha, ip6h, secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11497
		ip_drop_packet(first_mp, B_TRUE, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11498
		    &ipdrops_tcp_clear, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11499
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11500
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11502
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11503
	 * We have a secure packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11504
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11505
	if (act == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11506
		ipsec_log_policy_failure(tcp->tcp_wq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11507
		    IPSEC_POLICY_NOT_NEEDED, "tcp_check_policy", ipha, ip6h,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11508
		    secure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11509
		ip_drop_packet(first_mp, B_TRUE, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11510
		    &ipdrops_tcp_secure, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11511
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11512
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11514
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11515
	 * XXX This whole routine is currently incorrect.  ipl should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11516
	 * be set to the latch pointer, but is currently not set, so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11517
	 * we initialize it to NULL to avoid picking up random garbage.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11518
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11519
	if (ipl == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11520
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11522
	data_mp = first_mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11524
	ii = (ipsec_in_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11526
	if (ipsec_check_ipsecin_latch(ii, data_mp, ipl, ipha, ip6h, &reason,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11527
	    &counter)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11528
		BUMP_MIB(&ip_mib, ipsecInSucceeded);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11529
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11530
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 11531
	(void) strlog(TCP_MOD_ID, 0, 0, SL_ERROR|SL_WARN|SL_CONSOLE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11532
	    "tcp inbound policy mismatch: %s, packet dropped\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11533
	    reason);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11534
	BUMP_MIB(&ip_mib, ipsecInFailed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11535
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11536
	ip_drop_packet(first_mp, B_TRUE, NULL, NULL, counter, &tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11537
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11538
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11540
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11541
 * tcp_ss_rexmit() is called in tcp_rput_data() to do slow start
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11542
 * retransmission after a timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11543
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11544
 * To limit the number of duplicate segments, we limit the number of segment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11545
 * to be sent in one time to tcp_snd_burst, the burst variable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11546
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11547
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11548
tcp_ss_rexmit(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11549
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11550
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11551
	uint32_t	smax;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11552
	int32_t		win;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11553
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11554
	int32_t		off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11555
	int32_t		burst = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11556
	mblk_t		*snxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11557
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11558
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11559
	 * Note that tcp_rexmit can be set even though TCP has retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11560
	 * all unack'ed segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11561
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11562
	if (SEQ_LT(tcp->tcp_rexmit_nxt, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11563
		smax = tcp->tcp_rexmit_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11564
		snxt = tcp->tcp_rexmit_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11565
		if (SEQ_LT(snxt, tcp->tcp_suna)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11566
			snxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11567
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11568
		win = MIN(tcp->tcp_cwnd, tcp->tcp_swnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11569
		win -= snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11570
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11571
		snxt_mp = tcp_get_seg_mp(tcp, snxt, &off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11573
		while (SEQ_LT(snxt, smax) && (win > 0) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11574
		    (burst > 0) && (snxt_mp != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11575
			mblk_t	*xmit_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11576
			mblk_t	*old_snxt_mp = snxt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11577
			uint32_t cnt = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11579
			if (win < cnt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11580
				cnt = win;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11581
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11582
			if (SEQ_GT(snxt + cnt, smax)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11583
				cnt = smax - snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11584
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11585
			xmit_mp = tcp_xmit_mp(tcp, snxt_mp, cnt, &off,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11586
			    &snxt_mp, snxt, B_TRUE, &cnt, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11587
			if (xmit_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11588
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11590
			tcp_send_data(tcp, tcp->tcp_wq, xmit_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11591
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11592
			snxt += cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11593
			win -= cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11594
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11595
			 * Update the send timestamp to avoid false
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11596
			 * retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11597
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11598
			old_snxt_mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11599
			BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11600
			UPDATE_MIB(&tcp_mib, tcpRetransBytes, cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11602
			tcp->tcp_rexmit_nxt = snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11603
			burst--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11604
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11605
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11606
		 * If we have transmitted all we have at the time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11607
		 * we started the retranmission, we can leave
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11608
		 * the rest of the job to tcp_wput_data().  But we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11609
		 * need to check the send window first.  If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11610
		 * win is not 0, go on with tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11611
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11612
		if (SEQ_LT(snxt, smax) || win == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11613
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11614
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11615
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11616
	/* Only call tcp_wput_data() if there is data to be sent. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11617
	if (tcp->tcp_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11618
		tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11620
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11622
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11623
 * Process all TCP option in SYN segment.  Note that this function should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11624
 * be called after tcp_adapt_ire() is called so that the necessary info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11625
 * from IRE is already set in the tcp structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11626
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11627
 * This function sets up the correct tcp_mss value according to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11628
 * MSS option value and our header size.  It also sets up the window scale
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11629
 * and timestamp values, and initialize SACK info blocks.  But it does not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11630
 * change receive window size after setting the tcp_mss value.  The caller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11631
 * should do the appropriate change.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11632
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11633
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11634
tcp_process_options(tcp_t *tcp, tcph_t *tcph)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11635
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11636
	int options;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11637
	tcp_opt_t tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11638
	uint32_t mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11639
	char *tmp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11641
	tcpopt.tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11642
	options = tcp_parse_options(tcph, &tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11644
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11645
	 * Process MSS option.  Note that MSS option value does not account
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11646
	 * for IP or TCP options.  This means that it is equal to MTU - minimum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11647
	 * IP+TCP header size, which is 40 bytes for IPv4 and 60 bytes for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11648
	 * IPv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11649
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11650
	if (!(options & TCP_OPT_MSS_PRESENT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11651
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11652
			tcpopt.tcp_opt_mss = tcp_mss_def_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11653
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11654
			tcpopt.tcp_opt_mss = tcp_mss_def_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11655
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11656
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11657
			mss_max = tcp_mss_max_ipv4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11658
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11659
			mss_max = tcp_mss_max_ipv6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11660
		if (tcpopt.tcp_opt_mss < tcp_mss_min)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11661
			tcpopt.tcp_opt_mss = tcp_mss_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11662
		else if (tcpopt.tcp_opt_mss > mss_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11663
			tcpopt.tcp_opt_mss = mss_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11664
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11666
	/* Process Window Scale option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11667
	if (options & TCP_OPT_WSCALE_PRESENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11668
		tcp->tcp_snd_ws = tcpopt.tcp_opt_wscale;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11669
		tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11670
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11671
		tcp->tcp_snd_ws = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11672
		tcp->tcp_snd_ws_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11673
		tcp->tcp_rcv_ws = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11674
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11676
	/* Process Timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11677
	if ((options & TCP_OPT_TSTAMP_PRESENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11678
	    (tcp->tcp_snd_ts_ok || TCP_IS_DETACHED(tcp))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11679
		tmp_tcph = (char *)tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11681
		tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11682
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11683
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11684
		ASSERT(OK_32PTR(tmp_tcph));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11685
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11687
		/* Fill in our template header with basic timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11688
		tmp_tcph += tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11689
		tmp_tcph[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11690
		tmp_tcph[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11691
		tmp_tcph[2] = TCPOPT_TSTAMP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11692
		tmp_tcph[3] = TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11693
		tcp->tcp_hdr_len += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11694
		tcp->tcp_tcp_hdr_len += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11695
		tcp->tcp_tcph->th_offset_and_rsrvd[0] += (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11696
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11697
		tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11698
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11700
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11701
	 * Process SACK options.  If SACK is enabled for this connection,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11702
	 * then allocate the SACK info structure.  Note the following ways
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11703
	 * when tcp_snd_sack_ok is set to true.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11704
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11705
	 * For active connection: in tcp_adapt_ire() called in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11706
	 * tcp_rput_other(), or in tcp_rput_other() when tcp_sack_permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11707
	 * is checked.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11708
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11709
	 * For passive connection: in tcp_adapt_ire() called in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11710
	 * tcp_accept_comm().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11711
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11712
	 * That's the reason why the extra TCP_IS_DETACHED() check is there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11713
	 * That check makes sure that if we did not send a SACK OK option,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11714
	 * we will not enable SACK for this connection even though the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11715
	 * side sends us SACK OK option.  For active connection, the SACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11716
	 * info structure has already been allocated.  So we need to free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11717
	 * it if SACK is disabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11718
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11719
	if ((options & TCP_OPT_SACK_OK_PRESENT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11720
	    (tcp->tcp_snd_sack_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11721
	    (tcp_sack_permitted != 0 && TCP_IS_DETACHED(tcp)))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11722
		/* This should be true only in the passive case. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11723
		if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11724
			ASSERT(TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11725
			tcp->tcp_sack_info =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11726
			    kmem_cache_alloc(tcp_sack_info_cache, KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11727
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11728
		if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11729
			tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11730
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11731
			tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11732
			if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11733
				tcp->tcp_max_sack_blk = 3;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11734
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11735
				tcp->tcp_max_sack_blk = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11736
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11737
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11738
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11739
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11740
		 * Resetting tcp_snd_sack_ok to B_FALSE so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11741
		 * no SACK info will be used for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11742
		 * connection.  This assumes that SACK usage
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11743
		 * permission is negotiated.  This may need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11744
		 * to be changed once this is clarified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11745
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11746
		if (tcp->tcp_sack_info != NULL) {
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
 11747
			ASSERT(tcp->tcp_notsack_list == NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11748
			kmem_cache_free(tcp_sack_info_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11749
			    tcp->tcp_sack_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11750
			tcp->tcp_sack_info = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11751
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11752
		tcp->tcp_snd_sack_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11753
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11754
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11755
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11756
	 * Now we know the exact TCP/IP header length, subtract
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11757
	 * that from tcp_mss to get our side's MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11758
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11759
	tcp->tcp_mss -= tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11760
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11761
	 * Here we assume that the other side's header size will be equal to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11762
	 * our header size.  We calculate the real MSS accordingly.  Need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11763
	 * take into additional stuffs IPsec puts in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11764
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11765
	 * Real MSS = Opt.MSS - (our TCP/IP header - min TCP/IP header)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11766
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11767
	tcpopt.tcp_opt_mss -= tcp->tcp_hdr_len + tcp->tcp_ipsec_overhead -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11768
	    ((tcp->tcp_ipversion == IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11769
	    IP_SIMPLE_HDR_LENGTH : IPV6_HDR_LEN) + TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11771
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11772
	 * Set MSS to the smaller one of both ends of the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11773
	 * We should not have called tcp_mss_set() before, but our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11774
	 * side of the MSS should have been set to a proper value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11775
	 * by tcp_adapt_ire().  tcp_mss_set() will also set up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11776
	 * STREAM head parameters properly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11777
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11778
	 * If we have a larger-than-16-bit window but the other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11779
	 * didn't want to do window scale, tcp_rwnd_set() will take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11780
	 * care of that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11781
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11782
	tcp_mss_set(tcp, MIN(tcpopt.tcp_opt_mss, tcp->tcp_mss));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11783
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11785
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11786
 * Sends the T_CONN_IND to the listener. The caller calls this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11787
 * functions via squeue to get inside the listener's perimeter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11788
 * once the 3 way hand shake is done a T_CONN_IND needs to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11789
 * sent. As an optimization, the caller can call this directly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11790
 * if listener's perimeter is same as eager's.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11791
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11792
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11793
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11794
tcp_send_conn_ind(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11795
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11796
	conn_t			*lconnp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11797
	tcp_t			*listener = lconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11798
	tcp_t			*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11799
	struct T_conn_ind	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11800
	ipaddr_t 		*addr_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11801
	boolean_t		need_send_conn_ind = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11803
	/* retrieve the eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11804
	conn_ind = (struct T_conn_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11805
	ASSERT(conn_ind->OPT_offset != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11806
	    conn_ind->OPT_length == sizeof (intptr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11807
	bcopy(mp->b_rptr + conn_ind->OPT_offset, &tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11808
		conn_ind->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11809
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11810
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11811
	 * TLI/XTI applications will get confused by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11812
	 * sending eager as an option since it violates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11813
	 * the option semantics. So remove the eager as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11814
	 * option since TLI/XTI app doesn't need it anyway.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11815
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11816
	if (!TCP_IS_SOCKET(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11817
		conn_ind->OPT_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11818
		conn_ind->OPT_offset = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11819
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11820
	if (listener->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11821
	    TCP_IS_DETACHED(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11822
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11823
		 * If listener has closed, it would have caused a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11824
		 * a cleanup/blowoff to happen for the eager. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11825
		 * just need to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11826
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11827
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11828
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11829
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11832
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11833
	 * if the conn_req_q is full defer passing up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11834
	 * T_CONN_IND until space is availabe after t_accept()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11835
	 * processing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11836
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11837
	mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11838
	if (listener->tcp_conn_req_cnt_q < listener->tcp_conn_req_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11839
		tcp_t *tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11841
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11842
		 * The eager already has an extra ref put in tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11843
		 * so that it stays till accept comes back even though it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11844
		 * might get into TCPS_CLOSED as a result of a TH_RST etc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11845
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11846
		ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11847
		listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11848
		listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11849
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11850
		/* Move from SYN_RCVD to ESTABLISHED list  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11851
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11852
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11853
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11854
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11855
		tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11856
		tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11858
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11859
		 * Insert at end of the queue because sockfs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11860
		 * sends down T_CONN_RES in chronological
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11861
		 * order. Leaving the older conn indications
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11862
		 * at front of the queue helps reducing search
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11863
		 * time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11864
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11865
		tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11866
		if (tail != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11867
			tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11868
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11869
			listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11870
		listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11871
		tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11872
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11873
		 * Delay sending up the T_conn_ind until we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11874
		 * done with the eager. Once we have have sent up
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11875
		 * the T_conn_ind, the accept can potentially complete
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11876
		 * any time and release the refhold we have on the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11877
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11878
		need_send_conn_ind = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11879
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11880
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11881
		 * Defer connection on q0 and set deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11882
		 * connection bit true
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11883
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11884
		tcp->tcp_conn_def_q0 = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11885
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11886
		/* take tcp out of q0 ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11887
		tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11888
		    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11889
		tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11890
		    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11891
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11892
		/* ... and place it at the end of q0 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11893
		tcp->tcp_eager_prev_q0 = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11894
		tcp->tcp_eager_next_q0 = listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11895
		listener->tcp_eager_prev_q0->tcp_eager_next_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11896
		listener->tcp_eager_prev_q0 = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11897
		tcp->tcp_conn.tcp_eager_conn_ind = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11898
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11900
	/* we have timed out before */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11901
	if (tcp->tcp_syn_rcvd_timeout != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11902
		tcp->tcp_syn_rcvd_timeout = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11903
		listener->tcp_syn_rcvd_timeout--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11904
		if (listener->tcp_syn_defense &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11905
		    listener->tcp_syn_rcvd_timeout <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11906
		    (tcp_conn_req_max_q0 >> 5) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11907
		    10*MINUTES < TICK_TO_MSEC(lbolt64 -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11908
			listener->tcp_last_rcv_lbolt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11909
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11910
			 * Turn off the defense mode if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11911
			 * believe the SYN attack is over.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11912
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11913
			listener->tcp_syn_defense = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11914
			if (listener->tcp_ip_addr_cache) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11915
				kmem_free((void *)listener->tcp_ip_addr_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11916
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11917
				listener->tcp_ip_addr_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11918
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11919
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11920
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11921
	addr_cache = (ipaddr_t *)(listener->tcp_ip_addr_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11922
	if (addr_cache != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11923
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11924
		 * We have finished a 3-way handshake with this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11925
		 * remote host. This proves the IP addr is good.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11926
		 * Cache it!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11927
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11928
		addr_cache[IP_ADDR_CACHE_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11929
			tcp->tcp_remote)] = tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11930
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11931
	mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11932
	if (need_send_conn_ind)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11933
		putnext(listener->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11934
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11936
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11937
tcp_find_pktinfo(tcp_t *tcp, mblk_t *mp, uint_t *ipversp, uint_t *ip_hdr_lenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11938
    uint_t *ifindexp, ip6_pkt_t *ippp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11939
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11940
	in_pktinfo_t	*pinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11941
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11942
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11943
	mblk_t		*first_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11944
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11945
	uint_t 		ifindex = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11946
	ip6_pkt_t	ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11947
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11948
	uint_t		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11950
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11951
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11952
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11953
	ipp.ipp_fields = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11954
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11955
	switch DB_TYPE(mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11956
	case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11957
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11958
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11959
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11960
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11961
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11962
		if (DB_TYPE(mp) != M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11963
			freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11964
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11965
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11966
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11967
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11968
	case M_DATA:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11969
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11970
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11971
		cmn_err(CE_NOTE, "tcp_find_pktinfo: unknown db_type");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11972
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11973
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11974
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11975
	ipvers = IPH_HDR_VERSION(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11976
	if (ipvers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11977
		if (tcp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11978
			ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11979
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11980
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11981
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11982
		ipp.ipp_fields |= IPPF_HOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11983
		ipp.ipp_hoplimit = ((ipha_t *)rptr)->ipha_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11985
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11986
		 * If we have IN_PKTINFO in an M_CTL and tcp_ipv6_recvancillary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11987
		 * has TCP_IPV6_RECVPKTINFO set, pass I/F index along in ipp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11988
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11989
		if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11990
		    mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11991
			pinfo = (in_pktinfo_t *)first_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11992
			if ((MBLKL(first_mp) == sizeof (in_pktinfo_t)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11993
			    (pinfo->in_pkt_ulp_type == IN_PKTINFO) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11994
			    (pinfo->in_pkt_flags & IPF_RECVIF)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11995
				ipp.ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11996
				ipp.ipp_ifindex = pinfo->in_pkt_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11997
				ifindex = pinfo->in_pkt_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11998
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 11999
			freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12000
			mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12001
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12002
		ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12003
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12004
		ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12006
		ASSERT(ipvers == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12007
		ipp.ipp_fields = IPPF_HOPLIMIT | IPPF_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12008
		ipp.ipp_tclass = (ip6h->ip6_flow & 0x0FF00000) >> 20;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12009
		ipp.ipp_hoplimit = ip6h->ip6_hops;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12010
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12011
		if (ip6h->ip6_nxt != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12012
			uint8_t	nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12013
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12014
			/* Look for ifindex information */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12015
			if (ip6h->ip6_nxt == IPPROTO_RAW) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12016
				ip6i_t *ip6i = (ip6i_t *)ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12017
				if ((uchar_t *)&ip6i[1] > mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12018
					BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12019
					freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12020
					return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12021
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12023
				if (ip6i->ip6i_flags & IP6I_IFINDEX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12024
					ASSERT(ip6i->ip6i_ifindex != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12025
					ipp.ipp_fields |= IPPF_IFINDEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12026
					ipp.ipp_ifindex = ip6i->ip6i_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12027
					ifindex = ip6i->ip6i_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12028
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12029
				rptr = (uchar_t *)&ip6i[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12030
				mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12031
				if (rptr == mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12032
					mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12033
					mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12034
					freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12035
					mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12036
					rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12037
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12038
				if (MBLKL(mp) < IPV6_HDR_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12039
				    sizeof (tcph_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12040
					BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12041
					freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12042
					return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12043
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12044
				ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12045
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12047
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12048
			 * Find any potentially interesting extension headers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12049
			 * as well as the length of the IPv6 + extension
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12050
			 * headers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12051
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12052
			ip_hdr_len = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdrp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12053
			/* Verify if this is a TCP packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12054
			if (nexthdrp != IPPROTO_TCP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12055
				BUMP_MIB(&ip_mib, tcpInErrs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12056
				freemsg(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12057
				return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12058
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12059
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12060
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12061
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12062
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12064
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12065
	if (ipversp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12066
		*ipversp = ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12067
	if (ip_hdr_lenp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12068
		*ip_hdr_lenp = ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12069
	if (ippp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12070
		*ippp = ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12071
	if (ifindexp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12072
		*ifindexp = ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12073
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12074
		freeb(first_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12075
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12076
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12077
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12079
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12080
 * Handle M_DATA messages from IP. Its called directly from IP via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12081
 * squeue for AF_INET type sockets fast path. No M_CTL are expected
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12082
 * in this path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12083
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12084
 * For everything else (including AF_INET6 sockets with 'tcp_ipversion'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12085
 * v4 and v6), we are called through tcp_input() and a M_CTL can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12086
 * be present for options but tcp_find_pktinfo() deals with it. We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12087
 * only expect M_DATA packets after tcp_find_pktinfo() is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12088
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12089
 * The first argument is always the connp/tcp to which the mp belongs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12090
 * There are no exceptions to this rule. The caller has already put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12091
 * a reference on this connp/tcp and once tcp_rput_data() returns,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12092
 * the squeue will do the refrele.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12093
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12094
 * The TH_SYN for the listener directly go to tcp_conn_request via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12095
 * squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12096
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12097
 * sqp: NULL = recursive, sqp != NULL means called from squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12098
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12099
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12100
tcp_rput_data(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12101
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12102
	int32_t		bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12103
	int32_t		gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12104
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12105
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12106
	uint32_t	new_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12107
	uchar_t		*iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12108
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12109
	int32_t		rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12110
	uint32_t	seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12111
	int		seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12112
	uint_t		ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12113
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12114
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12115
	int		urp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12116
	tcp_opt_t	tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12117
	uint_t		ipvers;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12118
	ip6_pkt_t	ipp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12119
	boolean_t	ofo_seg = B_FALSE; /* Out of order segment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12120
	uint32_t	cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12121
	uint32_t	add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12122
	int		npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12123
	int		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12124
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12125
	squeue_t	*sqp = (squeue_t *)arg2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12126
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12128
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12129
	 * RST from fused tcp loopback peer should trigger an unfuse.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12130
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12131
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12132
		TCP_STAT(tcp_fusion_aborted);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12133
		tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12134
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12136
	iphdr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12137
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12138
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12140
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12141
	 * An AF_INET socket is not capable of receiving any pktinfo. Do inline
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12142
	 * processing here. For rest call tcp_find_pktinfo to fill up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12143
	 * necessary information.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12144
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12145
	if (IPCL_IS_TCP4(connp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12146
		ipvers = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12147
		ip_hdr_len = IPH_HDR_LENGTH(rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12148
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12149
		mp = tcp_find_pktinfo(tcp, mp, &ipvers, &ip_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12150
		    NULL, &ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12151
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12152
			TCP_STAT(tcp_rput_v6_error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12153
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12154
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12155
		iphdr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12156
		rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12157
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12158
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12159
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12160
	tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12161
	seg_seq = ABE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12162
	seg_ack = ABE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12163
	ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12164
	seg_len = (int)(mp->b_wptr - rptr) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12165
	    (ip_hdr_len + TCP_HDR_LENGTH(tcph));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12166
	if ((mp1 = mp->b_cont) != NULL && mp1->b_datap->db_type == M_DATA) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12167
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12168
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12169
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12170
			seg_len += (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12171
		} while ((mp1 = mp1->b_cont) != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12172
		    mp1->b_datap->db_type == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12173
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12175
	if (tcp->tcp_state == TCPS_TIME_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12176
		tcp_time_wait_processing(tcp, mp, seg_seq, seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12177
		    seg_len, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12178
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12179
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12181
	if (sqp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12182
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12183
		 * This is the correct place to update tcp_last_recv_time. Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12184
		 * that it is also updated for tcp structure that belongs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12185
		 * global and listener queues which do not really need updating.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12186
		 * But that should not cause any harm.  And it is updated for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12187
		 * all kinds of incoming segments, not only for data segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12188
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12189
		tcp->tcp_last_recv_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12190
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12192
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12193
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12194
	BUMP_LOCAL(tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12195
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_RECV_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12196
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12197
	if ((flags & TH_URG) && sqp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12198
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12199
		 * TCP can't handle urgent pointers that arrive before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12200
		 * the connection has been accept()ed since it can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12201
		 * buffer OOB data.  Discard segment if this happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12202
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12203
		 * Nor can it reassemble urgent pointers, so discard
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12204
		 * if it's not the next segment expected.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12205
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12206
		 * Otherwise, collapse chain into one mblk (discard if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12207
		 * that fails).  This makes sure the headers, retransmitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12208
		 * data, and new data all are in the same mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12209
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12210
		ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12211
		if (tcp->tcp_listener || !pullupmsg(mp, -1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12212
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12213
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12214
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12215
		/* Update pointers into message */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12216
		iphdr = rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12217
		tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12218
		if (SEQ_GT(seg_seq, tcp->tcp_rnxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12219
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12220
			 * Since we can't handle any data with this urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12221
			 * pointer that is out of sequence, we expunge
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12222
			 * the data.  This allows us to still register
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12223
			 * the urgent mark and generate the M_PCSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12224
			 * which we can do.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12225
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12226
			mp->b_wptr = (uchar_t *)tcph + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12227
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12228
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12229
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12231
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12232
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12233
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12234
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12235
			 * Note that our stack cannot send data before a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12236
			 * connection is established, therefore the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12237
			 * following check is valid.  Otherwise, it has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12238
			 * to be changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12239
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12240
			if (SEQ_LEQ(seg_ack, tcp->tcp_iss) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12241
			    SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12242
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12243
				if (flags & TH_RST)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12244
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12245
				tcp_xmit_ctl("TCPS_SYN_SENT-Bad_seq",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12246
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12247
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12248
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12249
			ASSERT(tcp->tcp_suna + 1 == seg_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12250
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12251
		if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12252
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12253
			if (flags & TH_ACK)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12254
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12255
				    ECONNREFUSED, 13);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12256
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12257
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12258
		if (!(flags & TH_SYN)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12259
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12260
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12261
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12263
		/* Process all TCP options. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12264
		tcp_process_options(tcp, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12265
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12266
		 * The following changes our rwnd to be a multiple of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12267
		 * MIN(peer MSS, our MSS) for performance reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12268
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12269
		(void) tcp_rwnd_set(tcp, MSS_ROUNDUP(tcp->tcp_rq->q_hiwat,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12270
		    tcp->tcp_mss));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12272
		/* Is the other end ECN capable? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12273
		if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12274
			if ((flags & (TH_ECE|TH_CWR)) != TH_ECE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12275
				tcp->tcp_ecn_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12276
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12277
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12278
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12279
		 * Clear ECN flags because it may interfere with later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12280
		 * processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12281
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12282
		flags &= ~(TH_ECE|TH_CWR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12284
		tcp->tcp_irs = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12285
		tcp->tcp_rack = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12286
		tcp->tcp_rnxt = seg_seq + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12287
		U32_TO_ABE32(tcp->tcp_rnxt, tcp->tcp_tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12288
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12289
			/* Allocate room for SACK options if needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12290
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12291
				(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12292
				    tcp->tcp_hdr_len + TCPOPT_MAX_SACK_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12293
				    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12294
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12295
				(void) mi_set_sth_wroff(tcp->tcp_rq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12296
				    tcp->tcp_hdr_len +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12297
				    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12298
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12299
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12300
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12301
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12302
			 * If we can't get the confirmation upstream, pretend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12303
			 * we didn't even see this one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12304
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12305
			 * XXX: how can we pretend we didn't see it if we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12306
			 * have updated rnxt et. al.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12307
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12308
			 * For loopback we defer sending up the T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12309
			 * until after some checks below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12310
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12311
			mp1 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12312
			if (!tcp_conn_con(tcp, iphdr, tcph, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12313
			    tcp->tcp_loopback ? &mp1 : NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12314
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12315
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12316
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12317
			/* SYN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12318
			if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12319
				tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12320
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12321
			/* One for the SYN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12322
			tcp->tcp_suna = tcp->tcp_iss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12323
			tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12324
			tcp->tcp_state = TCPS_ESTABLISHED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12326
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12327
			 * If SYN was retransmitted, need to reset all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12328
			 * retransmission info.  This is because this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12329
			 * segment will be treated as a dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12330
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12331
			if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12332
				tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12333
				tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12334
				tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12335
				tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12336
				    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12337
				tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12339
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12340
				 * Set tcp_cwnd back to 1 MSS, per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12341
				 * recommendation from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12342
				 * draft-floyd-incr-init-win-01.txt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12343
				 * Increasing TCP's Initial Window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12344
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12345
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12346
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12347
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12348
			tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12349
			tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12351
			new_swnd = BE16_TO_U16(tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12352
			tcp->tcp_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12353
			if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12354
				tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12355
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12356
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12357
			 * Always send the three-way handshake ack immediately
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12358
			 * in order to make the connection complete as soon as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12359
			 * possible on the accepting host.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12360
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12361
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12362
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12363
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12364
			 * Special case for loopback.  At this point we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12365
			 * received SYN-ACK from the remote endpoint.  In
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12366
			 * order to ensure that both endpoints reach the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12367
			 * fused state prior to any data exchange, the final
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12368
			 * ACK needs to be sent before we indicate T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12369
			 * to the module upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12370
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12371
			if (tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12372
				mblk_t *ack_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12374
				ASSERT(!tcp->tcp_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12375
				ASSERT(mp1 != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12376
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12377
				 * For loopback, we always get a pure SYN-ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12378
				 * and only need to send back the final ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12379
				 * with no data (this is because the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12380
				 * tcp is ours and we don't do T/TCP).  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12381
				 * final ACK triggers the passive side to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12382
				 * perform fusion in ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12383
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12384
				if ((ack_mp = tcp_ack_mp(tcp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12385
					if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12386
						(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12387
						    tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12388
						tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12389
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12390
					TCP_RECORD_TRACE(tcp, ack_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12391
					    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12392
					tcp_send_data(tcp, tcp->tcp_wq, ack_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12393
					BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12394
					BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12396
					/* Send up T_CONN_CON */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12397
					putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12398
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12399
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12400
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12401
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12402
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12403
				 * Forget fusion; we need to handle more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12404
				 * complex cases below.  Send the deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12405
				 * T_CONN_CON message upstream and proceed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12406
				 * as usual.  Mark this tcp as not capable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12407
				 * of fusion.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12408
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12409
				TCP_STAT(tcp_fusion_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12410
				tcp->tcp_unfusable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12411
				putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12412
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12413
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12414
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12415
			 * Check to see if there is data to be sent.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12416
			 * yes, set the transmit flag.  Then check to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12417
			 * if received data processing needs to be done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12418
			 * If not, go straight to xmit_check.  This short
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12419
			 * cut is OK as we don't support T/TCP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12420
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12421
			if (tcp->tcp_unsent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12422
				flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12423
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12424
			if (seg_len == 0 && !(flags & TH_URG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12425
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12426
				goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12427
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12428
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12429
			flags &= ~TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12430
			seg_seq++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12431
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12432
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12433
		tcp->tcp_state = TCPS_SYN_RCVD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12434
		mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, tcp->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12435
		    NULL, NULL, tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12436
		if (mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12437
			mblk_setcred(mp1, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12438
			DB_CPID(mp1) = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12439
			TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12440
			tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12441
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12442
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12443
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12444
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12445
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12446
		if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12447
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12448
			 * In this state, a SYN|ACK packet is either bogus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12449
			 * because the other side must be ACKing our SYN which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12450
			 * indicates it has seen the ACK for their SYN and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12451
			 * shouldn't retransmit it or we're crossing SYNs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12452
			 * on active open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12453
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12454
			if ((flags & TH_SYN) && !tcp->tcp_active_open) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12455
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12456
				tcp_xmit_ctl("TCPS_SYN_RCVD-bad_syn",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12457
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12458
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12459
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12460
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12461
			 * NOTE: RFC 793 pg. 72 says this should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12462
			 * tcp->tcp_suna <= seg_ack <= tcp->tcp_snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12463
			 * but that would mean we have an ack that ignored
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12464
			 * our SYN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12465
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12466
			if (SEQ_LEQ(seg_ack, tcp->tcp_suna) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12467
			    SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12468
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12469
				tcp_xmit_ctl("TCPS_SYN_RCVD-bad_ack",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12470
				    tcp, seg_ack, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12471
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12472
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12473
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12474
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12475
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12476
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12477
		 * Only a TLI listener can come through this path when a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12478
		 * acceptor is going back to be a listener and a packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12479
		 * for the acceptor hits the classifier. For a socket
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12480
		 * listener, this can never happen because a listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12481
		 * can never accept connection on itself and hence a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12482
		 * socket acceptor can not go back to being a listener.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12483
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12484
		ASSERT(!TCP_IS_SOCKET(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12485
		/*FALLTHRU*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12486
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12487
	case TCPS_BOUND: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12488
		conn_t	*new_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12490
		new_connp = ipcl_classify(mp, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12491
		if (new_connp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12492
			tcp_reinput(new_connp, mp, connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12493
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12494
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12495
		/* We failed to classify. For now just drop the packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12496
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12497
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12498
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12499
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12500
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12501
		 * Handle the case where the tcp_clean_death() has happened
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12502
		 * on a connection (application hasn't closed yet) but a packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12503
		 * was already queued on squeue before tcp_clean_death()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12504
		 * was processed. Calling tcp_clean_death() twice on same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12505
		 * connection can result in weird behaviour.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12506
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12507
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12508
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12509
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12510
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12511
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12513
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12514
	 * Already on the correct queue/perimeter.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12515
	 * If this is a detached connection and not an eager
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12516
	 * connection hanging off a listener then new data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12517
	 * (past the FIN) will cause a reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12518
	 * We do a special check here where it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12519
	 * is out of the main line, rather than check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12520
	 * if we are detached every time we see new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12521
	 * data down below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12522
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12523
	if (TCP_IS_DETACHED_NONEAGER(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12524
	    (seg_len > 0 && SEQ_GT(seg_seq + seg_len, tcp->tcp_rnxt))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12525
		BUMP_MIB(&tcp_mib, tcpInClosed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12526
		TCP_RECORD_TRACE(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12527
		    mp, TCP_TRACE_RECV_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12528
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12529
		tcp_xmit_ctl("new data when detached", tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12530
		    tcp->tcp_snxt, 0, TH_RST);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12531
		(void) tcp_clean_death(tcp, EPROTO, 12);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12532
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12533
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12534
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12535
	mp->b_rptr = (uchar_t *)tcph + TCP_HDR_LENGTH(tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12536
	urp = BE16_TO_U16(tcph->th_urp) - TCP_OLD_URP_INTERPRETATION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12537
	new_swnd = BE16_TO_U16(tcph->th_win) <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12538
	    ((tcph->th_flags[0] & TH_SYN) ? 0 : tcp->tcp_snd_ws);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12539
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12540
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12541
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12542
		if (!tcp_paws_check(tcp, tcph, &tcpopt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12543
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12544
			 * This segment is not acceptable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12545
			 * Drop it and send back an ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12546
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12547
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12548
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12549
			goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12550
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12551
	} else if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12552
		ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12553
		tcpopt.tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12554
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12555
		 * SACK info in already updated in tcp_parse_options.  Ignore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12556
		 * all other TCP options...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12557
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12558
		(void) tcp_parse_options(tcph, &tcpopt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12559
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12560
try_again:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12561
	gap = seg_seq - tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12562
	rgap = tcp->tcp_rwnd - (gap + seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12563
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12564
	 * gap is the amount of sequence space between what we expect to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12565
	 * and what we got for seg_seq.  A positive value for gap means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12566
	 * something got lost.  A negative value means we got some old stuff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12567
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12568
	if (gap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12569
		/* Old stuff present.  Is the SYN in there? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12570
		if (seg_seq == tcp->tcp_irs && (flags & TH_SYN) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12571
		    (seg_len != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12572
			flags &= ~TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12573
			seg_seq++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12574
			urp--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12575
			/* Recompute the gaps after noting the SYN. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12576
			goto try_again;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12577
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12578
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12579
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12580
		    (seg_len > -gap ? -gap : seg_len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12581
		/* Remove the old stuff from seg_len. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12582
		seg_len += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12583
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12584
		 * Anything left?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12585
		 * Make sure to check for unack'd FIN when rest of data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12586
		 * has been previously ack'd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12587
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12588
		if (seg_len < 0 || (seg_len == 0 && !(flags & TH_FIN))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12589
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12590
			 * Resets are only valid if they lie within our offered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12591
			 * window.  If the RST bit is set, we just ignore this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12592
			 * segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12593
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12594
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12595
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12596
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12597
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12598
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12599
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12600
			 * The arriving of dup data packets indicate that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12601
			 * may have postponed an ack for too long, or the other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12602
			 * side's RTT estimate is out of shape. Start acking
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12603
			 * more often.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12604
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12605
			if (SEQ_GEQ(seg_seq + seg_len - gap, tcp->tcp_rack) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12606
			    tcp->tcp_rack_cnt >= 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12607
			    tcp->tcp_rack_abs_max > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12608
				tcp->tcp_rack_abs_max--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12609
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12610
			tcp->tcp_rack_cur_max = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12612
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12613
			 * This segment is "unacceptable".  None of its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12614
			 * sequence space lies within our advertized window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12615
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12616
			 * Adjust seg_len to the original value for tracing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12617
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12618
			seg_len -= gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12619
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 12620
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12621
				    "tcp_rput: unacceptable, gap %d, rgap %d, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12622
				    "flags 0x%x, seg_seq %u, seg_ack %u, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12623
				    "seg_len %d, rnxt %u, snxt %u, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12624
				    gap, rgap, flags, seg_seq, seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12625
				    seg_len, tcp->tcp_rnxt, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12626
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12627
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12628
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12630
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12631
			 * Arrange to send an ACK in response to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12632
			 * unacceptable segment per RFC 793 page 69. There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12633
			 * is only one small difference between ours and the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12634
			 * acceptability test in the RFC - we accept ACK-only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12635
			 * packet with SEG.SEQ = RCV.NXT+RCV.WND and no ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12636
			 * will be generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12637
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12638
			 * Note that we have to ACK an ACK-only packet at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12639
			 * for stacks that send 0-length keep-alives with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12640
			 * SEG.SEQ = SND.NXT-1 as recommended by RFC1122,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12641
			 * section 4.2.3.6. As long as we don't ever generate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12642
			 * an unacceptable packet in response to an incoming
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12643
			 * packet that is unacceptable, it should not cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12644
			 * "ACK wars".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12645
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12646
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12648
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12649
			 * Continue processing this segment in order to use the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12650
			 * ACK information it contains, but skip all other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12651
			 * sequence-number processing.	Processing the ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12652
			 * information is necessary in order to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12653
			 * re-synchronize connections that may have lost
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12654
			 * synchronization.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12655
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12656
			 * We clear seg_len and flag fields related to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12657
			 * sequence number processing as they are not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12658
			 * to be trusted for an unacceptable segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12659
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12660
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12661
			flags &= ~(TH_SYN | TH_FIN | TH_URG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12662
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12663
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12664
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12665
		/* Fix seg_seq, and chew the gap off the front. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12666
		seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12667
		urp += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12668
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12669
			mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12670
			ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12671
			    (uintptr_t)UINT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12672
			gap += (uint_t)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12673
			if (gap > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12674
				mp->b_rptr = mp->b_wptr - gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12675
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12676
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12677
			mp2 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12678
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12679
			freeb(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12680
		} while (gap < 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12681
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12682
		 * If the urgent data has already been acknowledged, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12683
		 * should ignore TH_URG below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12684
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12685
		if (urp < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12686
			flags &= ~TH_URG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12687
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12688
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12689
	 * rgap is the amount of stuff received out of window.  A negative
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12690
	 * value is the amount out of window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12691
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12692
	if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12693
		mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12694
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12695
		if (tcp->tcp_rwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12696
			BUMP_MIB(&tcp_mib, tcpInWinProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12697
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12698
			BUMP_MIB(&tcp_mib, tcpInDataPastWinSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12699
			UPDATE_MIB(&tcp_mib, tcpInDataPastWinBytes, -rgap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12700
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12702
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12703
		 * seg_len does not include the FIN, so if more than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12704
		 * just the FIN is out of window, we act like we don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12705
		 * see it.  (If just the FIN is out of window, rgap
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12706
		 * will be zero and we will go ahead and acknowledge
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12707
		 * the FIN.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12708
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12709
		flags &= ~TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12710
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12711
		/* Fix seg_len and make sure there is something left. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12712
		seg_len += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12713
		if (seg_len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12714
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12715
			 * Resets are only valid if they lie within our offered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12716
			 * window.  If the RST bit is set, we just ignore this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12717
			 * segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12718
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12719
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12720
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12721
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12722
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12723
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12724
			/* Per RFC 793, we need to send back an ACK. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12725
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12727
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12728
			 * Send SIGURG as soon as possible i.e. even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12729
			 * if the TH_URG was delivered in a window probe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12730
			 * packet (which will be unacceptable).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12731
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12732
			 * We generate a signal if none has been generated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12733
			 * for this connection or if this is a new urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12734
			 * byte. Also send a zero-length "unmarked" message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12735
			 * to inform SIOCATMARK that this is not the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12736
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12737
			 * tcp_urp_last_valid is cleared when the T_exdata_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12738
			 * is sent up. This plus the check for old data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12739
			 * (gap >= 0) handles the wraparound of the sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12740
			 * number space without having to always track the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12741
			 * correct MAX(tcp_urp_last, tcp_rnxt). (BSD tracks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12742
			 * this max in its rcv_up variable).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12743
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12744
			 * This prevents duplicate SIGURGS due to a "late"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12745
			 * zero-window probe when the T_EXDATA_IND has already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12746
			 * been sent up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12747
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12748
			if ((flags & TH_URG) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12749
			    (!tcp->tcp_urp_last_valid || SEQ_GT(urp + seg_seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12750
			    tcp->tcp_urp_last))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12751
				mp1 = allocb(0, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12752
				if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12753
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12754
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12755
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12756
				if (!TCP_IS_DETACHED(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12757
				    !putnextctl1(tcp->tcp_rq, M_PCSIG,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12758
				    SIGURG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12759
					/* Try again on the rexmit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12760
					freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12761
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12762
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12763
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12764
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12765
				 * If the next byte would be the mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12766
				 * then mark with MARKNEXT else mark
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12767
				 * with NOTMARKNEXT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12768
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12769
				if (gap == 0 && urp == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12770
					mp1->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12771
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12772
					mp1->b_flag |= MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12773
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12774
				tcp->tcp_urp_mark_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12775
				flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12776
				tcp->tcp_urp_last_valid = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12777
				tcp->tcp_urp_last = urp + seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12778
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12779
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12780
			 * If this is a zero window probe, continue to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12781
			 * process the ACK part.  But we need to set seg_len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12782
			 * to 0 to avoid data processing.  Otherwise just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12783
			 * drop the segment and send back an ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12784
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12785
			if (tcp->tcp_rwnd == 0 && seg_seq == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12786
				flags &= ~(TH_SYN | TH_URG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12787
				seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12788
				goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12789
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12790
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12791
				goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12792
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12793
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12794
		/* Pitch out of window stuff off the end. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12795
		rgap = seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12796
		mp2 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12797
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12798
			ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12799
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12800
			rgap -= (int)(mp2->b_wptr - mp2->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12801
			if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12802
				mp2->b_wptr += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12803
				if ((mp1 = mp2->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12804
					mp2->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12805
					freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12806
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12807
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12808
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12809
		} while ((mp2 = mp2->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12810
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12811
ok:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12812
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12813
	 * TCP should check ECN info for segments inside the window only.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12814
	 * Therefore the check should be done here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12815
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12816
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12817
		if (flags & TH_CWR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12818
			tcp->tcp_ecn_echo_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12819
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12820
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12821
		 * Note that both ECN_CE and CWR can be set in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12822
		 * same segment.  In this case, we once again turn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12823
		 * on ECN_ECHO.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12824
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12825
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12826
			uchar_t tos = ((ipha_t *)rptr)->ipha_type_of_service;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12828
			if ((tos & IPH_ECN_CE) == IPH_ECN_CE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12829
				tcp->tcp_ecn_echo_on = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12830
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12831
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12832
			uint32_t vcf = ((ip6_t *)rptr)->ip6_vcf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12833
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12834
			if ((vcf & htonl(IPH_ECN_CE << 20)) ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12835
			    htonl(IPH_ECN_CE << 20)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12836
				tcp->tcp_ecn_echo_on = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12837
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12838
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12839
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12841
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12842
	 * Check whether we can update tcp_ts_recent.  This test is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12843
	 * NOT the one in RFC 1323 3.4.  It is from Braden, 1993, "TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12844
	 * Extensions for High Performance: An Update", Internet Draft.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12845
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12846
	if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12847
	    TSTMP_GEQ(tcpopt.tcp_opt_ts_val, tcp->tcp_ts_recent) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12848
	    SEQ_LEQ(seg_seq, tcp->tcp_rack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12849
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12850
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12851
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12853
	if (seg_seq != tcp->tcp_rnxt || tcp->tcp_reass_head) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12854
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12855
		 * FIN in an out of order segment.  We record this in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12856
		 * tcp_valid_bits and the seq num of FIN in tcp_ofo_fin_seq.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12857
		 * Clear the FIN so that any check on FIN flag will fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12858
		 * Remember that FIN also counts in the sequence number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12859
		 * space.  So we need to ack out of order FIN only segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12860
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12861
		if (flags & TH_FIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12862
			tcp->tcp_valid_bits |= TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12863
			tcp->tcp_ofo_fin_seq = seg_seq + seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12864
			flags &= ~TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12865
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12866
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12867
		if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12868
			/* Fill in the SACK blk list. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12869
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12870
				ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12871
				tcp_sack_insert(tcp->tcp_sack_list,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12872
				    seg_seq, seg_seq + seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12873
				    &(tcp->tcp_num_sack_blk));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12874
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12875
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12876
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12877
			 * Attempt reassembly and see if we have something
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12878
			 * ready to go.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12879
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12880
			mp = tcp_reass(tcp, mp, seg_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12881
			/* Always ack out of order packets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12882
			flags |= TH_ACK_NEEDED | TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12883
			if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12884
				ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12885
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12886
				seg_len = mp->b_cont ? msgdsize(mp) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12887
					(int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12888
				seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12889
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12890
				 * A gap is filled and the seq num and len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12891
				 * of the gap match that of a previously
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12892
				 * received FIN, put the FIN flag back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12893
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12894
				if ((tcp->tcp_valid_bits & TCP_OFO_FIN_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12895
				    seg_seq + seg_len == tcp->tcp_ofo_fin_seq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12896
					flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12897
					tcp->tcp_valid_bits &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12898
					    ~TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12899
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12900
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12901
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12902
				 * Keep going even with NULL mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12903
				 * There may be a useful ACK or something else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12904
				 * we don't want to miss.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12905
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12906
				 * But TCP should not perform fast retransmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12907
				 * because of the ack number.  TCP uses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12908
				 * seg_len == 0 to determine if it is a pure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12909
				 * ACK.  And this is not a pure ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12910
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12911
				seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12912
				ofo_seg = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12913
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12914
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12915
	} else if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12916
		BUMP_MIB(&tcp_mib, tcpInDataInorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12917
		UPDATE_MIB(&tcp_mib, tcpInDataInorderBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12918
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12919
		 * If an out of order FIN was received before, and the seq
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12920
		 * num and len of the new segment match that of the FIN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12921
		 * put the FIN flag back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12922
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12923
		if ((tcp->tcp_valid_bits & TCP_OFO_FIN_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12924
		    seg_seq + seg_len == tcp->tcp_ofo_fin_seq) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12925
			flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12926
			tcp->tcp_valid_bits &= ~TCP_OFO_FIN_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12927
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12928
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12929
	if ((flags & (TH_RST | TH_SYN | TH_URG | TH_ACK)) != TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12930
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12931
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12932
		switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12933
		case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12934
			(void) tcp_clean_death(tcp, ECONNREFUSED, 14);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12935
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12936
		case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12937
		case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12938
		case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12939
		case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12940
			(void) tcp_clean_death(tcp, ECONNRESET, 15);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12941
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12942
		case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12943
		case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12944
			(void) tcp_clean_death(tcp, 0, 16);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12945
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12946
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12947
			ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12948
			(void) tcp_clean_death(tcp, ENXIO, 17);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12949
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12950
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12951
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12952
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12953
	if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12954
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12955
		 * See RFC 793, Page 71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12956
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12957
		 * The seq number must be in the window as it should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12958
		 * be "fixed" above.  If it is outside window, it should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12959
		 * be already rejected.  Note that we allow seg_seq to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12960
		 * rnxt + rwnd because we want to accept 0 window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12961
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12962
		ASSERT(SEQ_GEQ(seg_seq, tcp->tcp_rnxt) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12963
		    SEQ_LEQ(seg_seq, tcp->tcp_rnxt + tcp->tcp_rwnd));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12964
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12965
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12966
		 * If the ACK flag is not set, just use our snxt as the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12967
		 * seq number of the RST segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12968
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12969
		if (!(flags & TH_ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12970
			seg_ack = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12971
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12972
		tcp_xmit_ctl("TH_SYN", tcp, seg_ack, seg_seq + 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12973
		    TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12974
		ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12975
		(void) tcp_clean_death(tcp, ECONNRESET, 18);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12976
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12977
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12978
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12979
	 * urp could be -1 when the urp field in the packet is 0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12980
	 * and TCP_OLD_URP_INTERPRETATION is set. This implies that the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12981
	 * byte was at seg_seq - 1, in which case we ignore the urgent flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12982
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12983
	if (flags & TH_URG && urp >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12984
		if (!tcp->tcp_urp_last_valid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12985
		    SEQ_GT(urp + seg_seq, tcp->tcp_urp_last)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12986
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12987
			 * If we haven't generated the signal yet for this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12988
			 * urgent pointer value, do it now.  Also, send up a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12989
			 * zero-length M_DATA indicating whether or not this is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12990
			 * the mark. The latter is not needed when a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12991
			 * T_EXDATA_IND is sent up. However, if there are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12992
			 * allocation failures this code relies on the sender
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12993
			 * retransmitting and the socket code for determining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12994
			 * the mark should not block waiting for the peer to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12995
			 * transmit. Thus, for simplicity we always send up the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12996
			 * mark indication.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12997
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12998
			mp1 = allocb(0, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 12999
			if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13000
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13001
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13002
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13003
			if (!TCP_IS_DETACHED(tcp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13004
			    !putnextctl1(tcp->tcp_rq, M_PCSIG, SIGURG)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13005
				/* Try again on the rexmit. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13006
				freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13007
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13008
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13009
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13010
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13011
			 * Mark with NOTMARKNEXT for now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13012
			 * The code below will change this to MARKNEXT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13013
			 * if we are at the mark.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13014
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13015
			 * If there are allocation failures (e.g. in dupmsg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13016
			 * below) the next time tcp_rput_data sees the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13017
			 * segment it will send up the MSG*MARKNEXT message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13018
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13019
			mp1->b_flag |= MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13020
			freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13021
			tcp->tcp_urp_mark_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13022
			flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13023
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13024
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13025
			    "tcp_rput: sent M_PCSIG 2 seq %x urp %x "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13026
			    "last %x, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13027
			    seg_seq, urp, tcp->tcp_urp_last,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13028
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13029
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13030
			tcp->tcp_urp_last_valid = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13031
			tcp->tcp_urp_last = urp + seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13032
		} else if (tcp->tcp_urp_mark_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13033
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13034
			 * An allocation failure prevented the previous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13035
			 * tcp_rput_data from sending up the allocated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13036
			 * MSG*MARKNEXT message - send it up this time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13037
			 * around.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13038
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13039
			flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13040
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13042
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13043
		 * If the urgent byte is in this segment, make sure that it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13044
		 * all by itself.  This makes it much easier to deal with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13045
		 * possibility of an allocation failure on the T_exdata_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13046
		 * Note that seg_len is the number of bytes in the segment, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13047
		 * urp is the offset into the segment of the urgent byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13048
		 * urp < seg_len means that the urgent byte is in this segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13049
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13050
		if (urp < seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13051
			if (seg_len != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13052
				uint32_t  tmp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13053
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13054
				 * Break it up and feed it back in.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13055
				 * Re-attach the IP header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13056
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13057
				mp->b_rptr = iphdr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13058
				if (urp > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13059
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13060
					 * There is stuff before the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13061
					 * byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13062
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13063
					mp1 = dupmsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13064
					if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13065
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13066
						 * Trim from urgent byte on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13067
						 * The rest will come back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13068
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13069
						(void) adjmsg(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13070
						    urp - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13071
						tcp_rput_data(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13072
						    mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13073
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13074
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13075
					(void) adjmsg(mp1, urp - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13076
					/* Feed this piece back in. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13077
					tmp_rnxt = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13078
					tcp_rput_data(connp, mp1, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13079
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13080
					 * If the data passed back in was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13081
					 * processed (ie: bad ACK) sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13082
					 * the remainder back in will cause a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13083
					 * loop. In this case, drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13084
					 * packet and let the sender try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13085
					 * sending a good packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13086
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13087
					if (tmp_rnxt == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13088
						freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13089
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13090
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13091
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13092
				if (urp != seg_len - 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13093
					uint32_t  tmp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13094
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13095
					 * There is stuff after the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13096
					 * byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13097
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13098
					mp1 = dupmsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13099
					if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13100
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13101
						 * Trim everything beyond the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13102
						 * urgent byte.  The rest will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13103
						 * come back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13104
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13105
						(void) adjmsg(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13106
						    urp + 1 - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13107
						tcp_rput_data(connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13108
						    mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13109
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13110
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13111
					(void) adjmsg(mp1, urp + 1 - seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13112
					tmp_rnxt = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13113
					tcp_rput_data(connp, mp1, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13114
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13115
					 * If the data passed back in was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13116
					 * processed (ie: bad ACK) sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13117
					 * the remainder back in will cause a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13118
					 * loop. In this case, drop the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13119
					 * packet and let the sender try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13120
					 * sending a good packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13121
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13122
					if (tmp_rnxt == tcp->tcp_rnxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13123
						freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13124
						return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13125
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13126
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13127
				tcp_rput_data(connp, mp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13128
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13129
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13130
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13131
			 * This segment contains only the urgent byte.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13132
			 * have to allocate the T_exdata_ind, if we can.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13133
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13134
			if (!tcp->tcp_urp_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13135
				struct T_exdata_ind *tei;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13136
				mp1 = allocb(sizeof (struct T_exdata_ind),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13137
				    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13138
				if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13139
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13140
					 * Sigh... It'll be back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13141
					 * Generate any MSG*MARK message now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13142
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13143
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13144
					seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13145
					if (flags & TH_SEND_URP_MARK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13148
						ASSERT(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13149
						tcp->tcp_urp_mark_mp->b_flag &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13150
							~MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13151
						tcp->tcp_urp_mark_mp->b_flag |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13152
							MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13153
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13154
					goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13155
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13156
				mp1->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13157
				tei = (struct T_exdata_ind *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13158
				tei->PRIM_type = T_EXDATA_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13159
				tei->MORE_flag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13160
				mp1->b_wptr = (uchar_t *)&tei[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13161
				tcp->tcp_urp_mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13162
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13163
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13164
				    "tcp_rput: allocated exdata_ind %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13165
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13166
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13167
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13168
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13169
				 * There is no need to send a separate MSG*MARK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13170
				 * message since the T_EXDATA_IND will be sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13171
				 * now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13172
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13173
				flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13174
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13175
				tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13176
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13177
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13178
			 * Now we are all set.  On the next putnext upstream,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13179
			 * tcp_urp_mp will be non-NULL and will get prepended
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13180
			 * to what has to be this piece containing the urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13181
			 * byte.  If for any reason we abort this segment below,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13182
			 * if it comes back, we will have this ready, or it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13183
			 * will get blown off in close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13184
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13185
		} else if (urp == seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13186
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13187
			 * The urgent byte is the next byte after this sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13188
			 * number. If there is data it is marked with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13189
			 * MSGMARKNEXT and any tcp_urp_mark_mp is discarded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13190
			 * since it is not needed. Otherwise, if the code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13191
			 * above just allocated a zero-length tcp_urp_mark_mp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13192
			 * message, that message is tagged with MSGMARKNEXT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13193
			 * Sending up these MSGMARKNEXT messages makes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13194
			 * SIOCATMARK work correctly even though
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13195
			 * the T_EXDATA_IND will not be sent up until the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13196
			 * urgent byte arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13197
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13198
			if (seg_len != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13199
				flags |= TH_MARKNEXT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13200
				freemsg(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13201
				tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13202
				flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13203
			} else if (tcp->tcp_urp_mark_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13204
				flags |= TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13205
				tcp->tcp_urp_mark_mp->b_flag &=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13206
					~MSGNOTMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13207
				tcp->tcp_urp_mark_mp->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13208
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13209
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13210
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13211
			    "tcp_rput: AT MARK, len %d, flags 0x%x, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13212
			    seg_len, flags,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13213
			    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13214
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13215
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13216
			/* Data left until we hit mark */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13217
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 13218
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13219
			    "tcp_rput: URP %d bytes left, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13220
			    urp - seg_len, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13221
			    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13222
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13223
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13224
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13226
process_ack:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13227
	if (!(flags & TH_ACK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13228
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13229
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13230
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13231
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13232
	bytes_acked = (int)(seg_ack - tcp->tcp_suna);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13233
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13234
	if (tcp->tcp_ipversion == IPV6_VERSION && bytes_acked > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13235
		tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13236
	if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13237
		if (tcp->tcp_conn.tcp_eager_conn_ind != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13238
			/* 3-way handshake complete - pass up the T_CONN_IND */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13239
			tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13240
			mblk_t	*mp = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13242
			tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13243
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13244
			 * We are here means eager is fine but it can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13245
			 * get a TH_RST at any point between now and till
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13246
			 * accept completes and disappear. We need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13247
			 * ensure that reference to eager is valid after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13248
			 * we get out of eager's perimeter. So we do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13249
			 * an extra refhold.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13250
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13251
			CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13253
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13254
			 * The listener also exists because of the refhold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13255
			 * done in tcp_conn_request. Its possible that it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13256
			 * might have closed. We will check that once we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13257
			 * get inside listeners context.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13258
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13259
			CONN_INC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13260
			if (listener->tcp_connp->conn_sqp ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13261
			    connp->conn_sqp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13262
				tcp_send_conn_ind(listener->tcp_connp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13263
				    listener->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13264
				CONN_DEC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13265
			} else if (!tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13266
				squeue_fill(listener->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13267
				    tcp_send_conn_ind,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13268
				    listener->tcp_connp, SQTAG_TCP_CONN_IND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13269
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13270
				squeue_enter(listener->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13271
				    tcp_send_conn_ind, listener->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13272
				    SQTAG_TCP_CONN_IND);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13273
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13274
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13276
		if (tcp->tcp_active_open) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13277
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13278
			 * We are seeing the final ack in the three way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13279
			 * hand shake of a active open'ed connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13280
			 * so we must send up a T_CONN_CON
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13281
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13282
			if (!tcp_conn_con(tcp, iphdr, tcph, mp, NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13283
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13284
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13285
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13286
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13287
			 * Don't fuse the loopback endpoints for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13288
			 * simultaneous active opens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13289
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13290
			if (tcp->tcp_loopback) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13291
				TCP_STAT(tcp_fusion_unfusable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13292
				tcp->tcp_unfusable = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13293
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13294
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13296
		tcp->tcp_suna = tcp->tcp_iss + 1;	/* One for the SYN */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13297
		bytes_acked--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13298
		/* SYN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13299
		if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13300
			tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13302
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13303
		 * If SYN was retransmitted, need to reset all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13304
		 * retransmission info as this segment will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13305
		 * treated as a dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13306
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13307
		if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13308
			tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13309
			tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13310
			tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13311
			tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13312
			    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13313
			tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13314
			tcp->tcp_cwnd = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13315
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13316
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13317
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13318
		 * We set the send window to zero here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13319
		 * This is needed if there is data to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13320
		 * processed already on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13321
		 * Later (at swnd_update label), the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13322
		 * "new_swnd > tcp_swnd" condition is satisfied
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13323
		 * the XMIT_NEEDED flag is set in the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13324
		 * (SYN_RCVD) state. This ensures tcp_wput_data() is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13325
		 * called if there is already data on queue in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13326
		 * this state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13327
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13328
		tcp->tcp_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13330
		if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13331
			tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13332
		tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13333
		tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13334
		tcp->tcp_state = TCPS_ESTABLISHED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13335
		tcp->tcp_valid_bits &= ~TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13336
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13337
		/* Fuse when both sides are in ESTABLISHED state */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13338
		if (tcp->tcp_loopback && do_tcp_fusion)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13339
			tcp_fuse(tcp, iphdr, tcph);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13340
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13341
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13342
	/* This code follows 4.4BSD-Lite2 mostly. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13343
	if (bytes_acked < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13344
		goto est;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13346
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13347
	 * If TCP is ECN capable and the congestion experience bit is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13348
	 * set, reduce tcp_cwnd and tcp_ssthresh.  But this should only be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13349
	 * done once per window (or more loosely, per RTT).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13350
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13351
	if (tcp->tcp_cwr && SEQ_GT(seg_ack, tcp->tcp_cwr_snd_max))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13352
		tcp->tcp_cwr = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13353
	if (tcp->tcp_ecn_ok && (flags & TH_ECE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13354
		if (!tcp->tcp_cwr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13355
			npkt = ((tcp->tcp_snxt - tcp->tcp_suna) >> 1) / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13356
			tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13357
			tcp->tcp_cwnd = npkt * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13358
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13359
			 * If the cwnd is 0, use the timer to clock out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13360
			 * new segments.  This is required by the ECN spec.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13361
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13362
			if (npkt == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13363
				TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13364
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13365
				 * This makes sure that when the ACK comes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13366
				 * back, we will increase tcp_cwnd by 1 MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13367
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13368
				tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13369
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13370
			tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13371
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13372
			 * This marks the end of the current window of in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13373
			 * flight data.  That is why we don't use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13374
			 * tcp_suna + tcp_swnd.  Only data in flight can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13375
			 * provide ECN info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13376
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13377
			tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13378
			tcp->tcp_ecn_cwr_sent = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13379
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13380
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13382
	mp1 = tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13383
	if (bytes_acked == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13384
		if (!ofo_seg && seg_len == 0 && new_swnd == tcp->tcp_swnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13385
			int dupack_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13387
			BUMP_MIB(&tcp_mib, tcpInDupAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13388
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13389
			 * Fast retransmit.  When we have seen exactly three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13390
			 * identical ACKs while we have unacked data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13391
			 * outstanding we take it as a hint that our peer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13392
			 * dropped something.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13393
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13394
			 * If TCP is retransmitting, don't do fast retransmit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13395
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13396
			if (mp1 && tcp->tcp_suna != tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13397
			    ! tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13398
				/* Do Limited Transmit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13399
				if ((dupack_cnt = ++tcp->tcp_dupack_cnt) <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13400
				    tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13401
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13402
					 * RFC 3042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13403
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13404
					 * What we need to do is temporarily
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13405
					 * increase tcp_cwnd so that new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13406
					 * data can be sent if it is allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13407
					 * by the receive window (tcp_rwnd).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13408
					 * tcp_wput_data() will take care of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13409
					 * the rest.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13410
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13411
					 * If the connection is SACK capable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13412
					 * only do limited xmit when there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13413
					 * is SACK info.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13414
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13415
					 * Note how tcp_cwnd is incremented.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13416
					 * The first dup ACK will increase
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13417
					 * it by 1 MSS.  The second dup ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13418
					 * will increase it by 2 MSS.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13419
					 * means that only 1 new segment will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13420
					 * be sent for each dup ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13421
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13422
					if (tcp->tcp_unsent > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13423
					    (!tcp->tcp_snd_sack_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13424
					    (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13425
					    tcp->tcp_notsack_list != NULL))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13426
						tcp->tcp_cwnd += mss <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13427
						    (tcp->tcp_dupack_cnt - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13428
						flags |= TH_LIMIT_XMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13429
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13430
				} else if (dupack_cnt ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13431
				    tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13433
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13434
				 * If we have reduced tcp_ssthresh
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13435
				 * because of ECN, do not reduce it again
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13436
				 * unless it is already one window of data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13437
				 * away.  After one window of data, tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13438
				 * should then be cleared.  Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13439
				 * for non ECN capable connection, tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13440
				 * should always be false.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13441
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13442
				 * Adjust cwnd since the duplicate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13443
				 * ack indicates that a packet was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13444
				 * dropped (due to congestion.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13445
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13446
				if (!tcp->tcp_cwr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13447
					npkt = ((tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13448
					    tcp->tcp_suna) >> 1) / mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13449
					tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13450
					    mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13451
					tcp->tcp_cwnd = (npkt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13452
					    tcp->tcp_dupack_cnt) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13453
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13454
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13455
					tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13456
					tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13457
					tcp->tcp_ecn_cwr_sent = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13458
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13459
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13460
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13461
				 * We do Hoe's algorithm.  Refer to her
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13462
				 * paper "Improving the Start-up Behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13463
				 * of a Congestion Control Scheme for TCP,"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13464
				 * appeared in SIGCOMM'96.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13465
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13466
				 * Save highest seq no we have sent so far.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13467
				 * Be careful about the invisible FIN byte.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13468
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13469
				if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13470
				    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13471
					tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13472
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13473
					tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13474
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13475
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13476
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13477
				 * Do not allow bursty traffic during.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13478
				 * fast recovery.  Refer to Fall and Floyd's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13479
				 * paper "Simulation-based Comparisons of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13480
				 * Tahoe, Reno and SACK TCP" (in CCR?)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13481
				 * This is a best current practise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13482
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13483
				tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13485
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13486
				 * For SACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13487
				 * Calculate tcp_pipe, which is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13488
				 * estimated number of bytes in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13489
				 * network.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13490
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13491
				 * tcp_fack is the highest sack'ed seq num
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13492
				 * TCP has received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13493
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13494
				 * tcp_pipe is explained in the above quoted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13495
				 * Fall and Floyd's paper.  tcp_fack is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13496
				 * explained in Mathis and Mahdavi's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13497
				 * "Forward Acknowledgment: Refining TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13498
				 * Congestion Control" in SIGCOMM '96.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13499
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13500
				if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13501
					ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13502
					if (tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13503
						tcp->tcp_pipe = tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13504
						    tcp->tcp_fack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13505
						tcp->tcp_sack_snxt = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13506
						flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13507
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13508
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13509
						 * Always initialize tcp_pipe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13510
						 * even though we don't have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13511
						 * any SACK info.  If later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13512
						 * we get SACK info and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13513
						 * tcp_pipe is not initialized,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13514
						 * funny things will happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13515
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13516
						tcp->tcp_pipe =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13517
						    tcp->tcp_cwnd_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13518
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13519
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13520
					flags |= TH_REXMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13521
				} /* tcp_snd_sack_ok */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13522
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13523
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13524
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13525
					 * Here we perform congestion
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13526
					 * avoidance, but NOT slow start.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13527
					 * This is known as the Fast
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13528
					 * Recovery Algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13529
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13530
					if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13531
					    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13532
						flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13533
						tcp->tcp_pipe -= mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13534
						if (tcp->tcp_pipe < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13535
							tcp->tcp_pipe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13536
					} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13537
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13538
					 * We know that one more packet has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13539
					 * left the pipe thus we can update
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13540
					 * cwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13541
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13542
					cwnd = tcp->tcp_cwnd + mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13543
					if (cwnd > tcp->tcp_cwnd_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13544
						cwnd = tcp->tcp_cwnd_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13545
					tcp->tcp_cwnd = cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13546
					if (tcp->tcp_unsent > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13547
						flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13548
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13549
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13550
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13551
		} else if (tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13552
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13553
			 * If the window has opened, need to arrange
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13554
			 * to send additional data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13555
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13556
			if (new_swnd != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13557
				/* tcp_suna != tcp_snxt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13558
				/* Packet contains a window update */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13559
				BUMP_MIB(&tcp_mib, tcpInWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13560
				tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13561
				tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13562
				tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13564
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13565
				 * Transmit starting with tcp_suna since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13566
				 * the one byte probe is not ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13567
				 * If TCP has sent more than one identical
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13568
				 * probe, tcp_rexmit will be set.  That means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13569
				 * tcp_ss_rexmit() will send out the one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13570
				 * byte along with new data.  Otherwise,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13571
				 * fake the retransmission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13572
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13573
				flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13574
				if (!tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13575
					tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13576
					tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13577
					tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13578
					tcp->tcp_rexmit_max = tcp->tcp_suna + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13579
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13580
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13581
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13582
		goto swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13583
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13585
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13586
	 * Check for "acceptability" of ACK value per RFC 793, pages 72 - 73.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13587
	 * If the ACK value acks something that we have not yet sent, it might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13588
	 * be an old duplicate segment.  Send an ACK to re-synchronize the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13589
	 * other side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13590
	 * Note: reset in response to unacceptable ACK in SYN_RECEIVE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13591
	 * state is handled above, so we can always just drop the segment and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13592
	 * send an ACK here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13593
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13594
	 * Should we send ACKs in response to ACK only segments?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13595
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13596
	if (SEQ_GT(seg_ack, tcp->tcp_snxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13597
		BUMP_MIB(&tcp_mib, tcpInAckUnsent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13598
		/* drop the received segment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13599
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13601
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13602
		 * Send back an ACK.  If tcp_drop_ack_unsent_cnt is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13603
		 * greater than 0, check if the number of such
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13604
		 * bogus ACks is greater than that count.  If yes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13605
		 * don't send back any ACK.  This prevents TCP from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13606
		 * getting into an ACK storm if somehow an attacker
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13607
		 * successfully spoofs an acceptable segment to our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13608
		 * peer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13609
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13610
		if (tcp_drop_ack_unsent_cnt > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13611
		    ++tcp->tcp_in_ack_unsent > tcp_drop_ack_unsent_cnt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13612
			TCP_STAT(tcp_in_ack_unsent_drop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13613
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13614
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13615
		mp = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13616
		if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13617
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13618
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13619
			BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13620
			tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13621
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13622
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13623
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13624
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13625
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13626
	 * TCP gets a new ACK, update the notsack'ed list to delete those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13627
	 * blocks that are covered by this ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13628
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13629
	if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13630
		tcp_notsack_remove(&(tcp->tcp_notsack_list), seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13631
		    &(tcp->tcp_num_notsack_blk), &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13632
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13634
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13635
	 * If we got an ACK after fast retransmit, check to see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13636
	 * if it is a partial ACK.  If it is not and the congestion
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13637
	 * window was inflated to account for the other side's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13638
	 * cached packets, retract it.  If it is, do Hoe's algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13639
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13640
	if (tcp->tcp_dupack_cnt >= tcp_dupack_fast_retransmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13641
		ASSERT(tcp->tcp_rexmit == B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13642
		if (SEQ_GEQ(seg_ack, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13643
			tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13644
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13645
			 * Restore the orig tcp_cwnd_ssthresh after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13646
			 * fast retransmit phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13647
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13648
			if (tcp->tcp_cwnd > tcp->tcp_cwnd_ssthresh) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13649
				tcp->tcp_cwnd = tcp->tcp_cwnd_ssthresh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13650
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13651
			tcp->tcp_rexmit_max = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13652
			tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13653
			tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13654
			    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13656
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13657
			 * Remove all notsack info to avoid confusion with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13658
			 * the next fast retrasnmit/recovery phase.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13659
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13660
			if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13661
			    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13662
				TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13663
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13664
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13665
			if (tcp->tcp_snd_sack_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13666
			    tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13667
				flags |= TH_NEED_SACK_REXMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13668
				tcp->tcp_pipe -= mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13669
				if (tcp->tcp_pipe < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13670
					tcp->tcp_pipe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13671
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13672
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13673
				 * Hoe's algorithm:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13674
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13675
				 * Retransmit the unack'ed segment and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13676
				 * restart fast recovery.  Note that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13677
				 * need to scale back tcp_cwnd to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13678
				 * original value when we started fast
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13679
				 * recovery.  This is to prevent overly
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13680
				 * aggressive behaviour in sending new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13681
				 * segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13682
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13683
				tcp->tcp_cwnd = tcp->tcp_cwnd_ssthresh +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13684
					tcp_dupack_fast_retransmit * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13685
				tcp->tcp_cwnd_cnt = tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13686
				flags |= TH_REXMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13687
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13688
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13689
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13690
		tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13691
		if (tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13692
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13693
			 * TCP is retranmitting.  If the ACK ack's all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13694
			 * outstanding data, update tcp_rexmit_max and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13695
			 * tcp_rexmit_nxt.  Otherwise, update tcp_rexmit_nxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13696
			 * to the correct value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13697
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13698
			 * Note that SEQ_LEQ() is used.  This is to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13699
			 * unnecessary fast retransmit caused by dup ACKs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13700
			 * received when TCP does slow start retransmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13701
			 * after a time out.  During this phase, TCP may
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13702
			 * send out segments which are already received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13703
			 * This causes dup ACKs to be sent back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13704
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13705
			if (SEQ_LEQ(seg_ack, tcp->tcp_rexmit_max)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13706
				if (SEQ_GT(seg_ack, tcp->tcp_rexmit_nxt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13707
					tcp->tcp_rexmit_nxt = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13708
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13709
				if (seg_ack != tcp->tcp_rexmit_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13710
					flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13711
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13712
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13713
				tcp->tcp_rexmit = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13714
				tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13715
				tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13716
				tcp->tcp_snd_burst = tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13717
				    TCP_CWND_INFINITE : TCP_CWND_NORMAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13718
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13719
			tcp->tcp_ms_we_have_waited = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13720
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13721
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13723
	BUMP_MIB(&tcp_mib, tcpInAckSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13724
	UPDATE_MIB(&tcp_mib, tcpInAckBytes, bytes_acked);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13725
	tcp->tcp_suna = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13726
	if (tcp->tcp_zero_win_probe != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13727
		tcp->tcp_zero_win_probe = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13728
		tcp->tcp_timer_backoff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13729
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13730
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13731
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13732
	 * If tcp_xmit_head is NULL, then it must be the FIN being ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13733
	 * Note that it cannot be the SYN being ack'ed.  The code flow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13734
	 * will not reach here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13735
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13736
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13737
		goto fin_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13738
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13740
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13741
	 * Update the congestion window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13742
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13743
	 * If TCP is not ECN capable or TCP is ECN capable but the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13744
	 * congestion experience bit is not set, increase the tcp_cwnd as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13745
	 * usual.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13746
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13747
	if (!tcp->tcp_ecn_ok || !(flags & TH_ECE)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13748
		cwnd = tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13749
		add = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13751
		if (cwnd >= tcp->tcp_cwnd_ssthresh) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13752
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13753
			 * This is to prevent an increase of less than 1 MSS of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13754
			 * tcp_cwnd.  With partial increase, tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13755
			 * may send out tinygrams in order to preserve mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13756
			 * boundaries.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13757
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13758
			 * By initializing tcp_cwnd_cnt to new tcp_cwnd and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13759
			 * decrementing it by 1 MSS for every ACKs, tcp_cwnd is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13760
			 * increased by 1 MSS for every RTTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13761
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13762
			if (tcp->tcp_cwnd_cnt <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13763
				tcp->tcp_cwnd_cnt = cwnd + add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13764
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13765
				tcp->tcp_cwnd_cnt -= add;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13766
				add = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13767
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13768
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13769
		tcp->tcp_cwnd = MIN(cwnd + add, tcp->tcp_cwnd_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13770
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13772
	/* See if the latest urgent data has been acknowledged */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13773
	if ((tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13774
	    SEQ_GT(seg_ack, tcp->tcp_urg))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13775
		tcp->tcp_valid_bits &= ~TCP_URG_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13777
	/* Can we update the RTT estimates? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13778
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13779
		/* Ignore zero timestamp echo-reply. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13780
		if (tcpopt.tcp_opt_ts_ecr != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13781
			tcp_set_rto(tcp, (int32_t)lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13782
			    (int32_t)tcpopt.tcp_opt_ts_ecr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13783
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13785
		/* If needed, restart the timer. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13786
		if (tcp->tcp_set_timer == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13787
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13788
			tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13789
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13790
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13791
		 * Update tcp_csuna in case the other side stops sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13792
		 * us timestamps.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13793
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13794
		tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13795
	} else if (SEQ_GT(seg_ack, tcp->tcp_csuna)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13796
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13797
		 * An ACK sequence we haven't seen before, so get the RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13798
		 * and update the RTO. But first check if the timestamp is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13799
		 * valid to use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13800
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13801
		if ((mp1->b_next != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13802
		    SEQ_GT(seg_ack, (uint32_t)(uintptr_t)(mp1->b_next)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13803
			tcp_set_rto(tcp, (int32_t)lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13804
			    (int32_t)(intptr_t)mp1->b_prev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13805
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13806
			BUMP_MIB(&tcp_mib, tcpRttNoUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13808
		/* Remeber the last sequence to be ACKed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13809
		tcp->tcp_csuna = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13810
		if (tcp->tcp_set_timer == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13811
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13812
			tcp->tcp_set_timer = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13813
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13814
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13815
		BUMP_MIB(&tcp_mib, tcpRttNoUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13816
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13817
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13818
	/* Eat acknowledged bytes off the xmit queue. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13819
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13820
		mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13821
		uchar_t	*wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13822
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13823
		wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13824
		ASSERT((uintptr_t)(wptr - mp1->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13825
		bytes_acked -= (int)(wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13826
		if (bytes_acked < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13827
			mp1->b_rptr = wptr + bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13828
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13829
			 * Set a new timestamp if all the bytes timed by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13830
			 * old timestamp have been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13831
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13832
			if (SEQ_GT(seg_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13833
			    (uint32_t)(uintptr_t)(mp1->b_next))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13834
				mp1->b_prev = (mblk_t *)(uintptr_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13835
				mp1->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13836
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13837
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13838
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13839
		mp1->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13840
		mp1->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13841
		mp2 = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13842
		mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13844
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13845
		 * This notification is required for some zero-copy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13846
		 * clients to maintain a copy semantic. After the data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13847
		 * is ack'ed, client is safe to modify or reuse the buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13848
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13849
		if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13850
		    (mp2->b_datap->db_struioflag & STRUIO_ZCNOTIFY))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13851
			tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13852
		freeb(mp2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13853
		if (bytes_acked == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13854
			if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13855
				/* Everything is ack'ed, clear the tail. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13856
				tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13857
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13858
				 * Cancel the timer unless we are still
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13859
				 * waiting for an ACK for the FIN packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13860
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13861
				if (tcp->tcp_timer_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13862
				    tcp->tcp_snxt == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13863
					(void) TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13864
					    tcp->tcp_timer_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13865
					tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13866
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13867
				goto pre_swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13868
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13869
			if (mp2 != tcp->tcp_xmit_tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13870
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13871
			tcp->tcp_xmit_tail = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13872
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13873
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13874
			tcp->tcp_xmit_tail_unsent = (int)(mp1->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13875
			    mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13876
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13877
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13878
		if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13879
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13880
			 * More was acked but there is nothing more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13881
			 * outstanding.  This means that the FIN was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13882
			 * just acked or that we're talking to a clown.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13883
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13884
fin_acked:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13885
			ASSERT(tcp->tcp_fin_sent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13886
			tcp->tcp_xmit_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13887
			if (tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13888
				/* FIN was acked - making progress */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13889
				if (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13890
				    !tcp->tcp_fin_acked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13891
					tcp->tcp_ip_forward_progress = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13892
				tcp->tcp_fin_acked = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13893
				if (tcp->tcp_linger_tid != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13894
				    TCP_TIMER_CANCEL(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13895
					tcp->tcp_linger_tid) >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13896
					tcp_stop_lingering(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13897
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13898
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13899
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13900
				 * We should never get here because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13901
				 * we have already checked that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13902
				 * number of bytes ack'ed should be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13903
				 * smaller than or equal to what we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13904
				 * have sent so far (it is the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13905
				 * acceptability check of the ACK).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13906
				 * We can only get here if the send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13907
				 * queue is corrupted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13908
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13909
				 * Terminate the connection and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13910
				 * panic the system.  It is better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13911
				 * for us to panic instead of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13912
				 * continuing to avoid other disaster.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13913
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13914
				tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13915
				    tcp->tcp_rnxt, TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13916
				panic("Memory corruption "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13917
				    "detected for connection %s.",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13918
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13919
					DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13920
				/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13921
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13922
			goto pre_swnd_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13923
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13924
		ASSERT(mp2 != tcp->tcp_xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13925
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13926
	if (tcp->tcp_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13927
		flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13928
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13929
pre_swnd_update:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13930
	tcp->tcp_xmit_head = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13931
swnd_update:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13932
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13933
	 * The following check is different from most other implementations.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13934
	 * For bi-directional transfer, when segments are dropped, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13935
	 * "normal" check will not accept a window update in those
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13936
	 * retransmitted segemnts.  Failing to do that, TCP may send out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13937
	 * segments which are outside receiver's window.  As TCP accepts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13938
	 * the ack in those retransmitted segments, if the window update in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13939
	 * the same segment is not accepted, TCP will incorrectly calculates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13940
	 * that it can send more segments.  This can create a deadlock
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13941
	 * with the receiver if its window becomes zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13942
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13943
	if (SEQ_LT(tcp->tcp_swl2, seg_ack) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13944
	    SEQ_LT(tcp->tcp_swl1, seg_seq) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13945
	    (tcp->tcp_swl1 == seg_seq && new_swnd > tcp->tcp_swnd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13946
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13947
		 * The criteria for update is:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13948
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13949
		 * 1. the segment acknowledges some data.  Or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13950
		 * 2. the segment is new, i.e. it has a higher seq num. Or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13951
		 * 3. the segment is not old and the advertised window is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13952
		 * larger than the previous advertised window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13953
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13954
		if (tcp->tcp_unsent && new_swnd > tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13955
			flags |= TH_XMIT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13956
		tcp->tcp_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13957
		if (new_swnd > tcp->tcp_max_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13958
			tcp->tcp_max_swnd = new_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13959
		tcp->tcp_swl1 = seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13960
		tcp->tcp_swl2 = seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13961
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13962
est:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13963
	if (tcp->tcp_state > TCPS_ESTABLISHED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13964
		switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13965
		case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13966
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13967
				tcp->tcp_state = TCPS_FIN_WAIT_2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13968
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13969
				 * We implement the non-standard BSD/SunOS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13970
				 * FIN_WAIT_2 flushing algorithm.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13971
				 * If there is no user attached to this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13972
				 * TCP endpoint, then this TCP struct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13973
				 * could hang around forever in FIN_WAIT_2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13974
				 * state if the peer forgets to send us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13975
				 * a FIN.  To prevent this, we wait only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13976
				 * 2*MSL (a convenient time value) for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13977
				 * the FIN to arrive.  If it doesn't show up,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13978
				 * we flush the TCP endpoint.  This algorithm,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13979
				 * though a violation of RFC-793, has worked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13980
				 * for over 10 years in BSD systems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13981
				 * Note: SunOS 4.x waits 675 seconds before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13982
				 * flushing the FIN_WAIT_2 connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13983
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13984
				TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13985
				    tcp_fin_wait_2_flush_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13986
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13987
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13988
		case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13989
			break;	/* Shutdown hook? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13990
		case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13991
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13992
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13993
				(void) tcp_clean_death(tcp, 0, 19);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13994
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13995
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13996
			goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13997
		case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13998
			if (tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 13999
				tcp->tcp_state = TCPS_TIME_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14000
				if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14001
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14002
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14003
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14004
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14005
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14006
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14007
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14008
			/*FALLTHRU*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14009
		case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14010
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14011
			goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14012
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14013
			ASSERT(tcp->tcp_state != TCPS_TIME_WAIT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14014
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14015
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14016
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14017
	if (flags & TH_FIN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14018
		/* Make sure we ack the fin */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14019
		flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14020
		if (!tcp->tcp_fin_rcvd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14021
			tcp->tcp_fin_rcvd = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14022
			tcp->tcp_rnxt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14023
			tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14024
			U32_TO_ABE32(tcp->tcp_rnxt, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14026
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14027
			 * Generate the ordrel_ind at the end unless we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14028
			 * are an eager guy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14029
			 * In the eager case tcp_rsrv will do this when run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14030
			 * after tcp_accept is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14031
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14032
			if (tcp->tcp_listener == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14033
			    !TCP_IS_DETACHED(tcp) && (!tcp->tcp_hard_binding))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14034
				flags |= TH_ORDREL_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14035
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14036
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14037
			case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14038
				tcp->tcp_state = TCPS_CLOSE_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14039
				/* Keepalive? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14040
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14041
			case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14042
				if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14043
					tcp->tcp_state = TCPS_CLOSING;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14044
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14045
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14046
				/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14047
			case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14048
				tcp->tcp_state = TCPS_TIME_WAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14049
				if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14050
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14051
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14052
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14053
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14054
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14055
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14056
				if (seg_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14057
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14058
					 * implies data piggybacked on FIN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14059
					 * break to handle data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14060
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14061
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14062
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14063
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14064
				goto ack_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14065
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14066
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14067
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14068
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14069
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14070
	if (seg_len == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14071
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14072
		goto xmit_check;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14073
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14074
	if (mp->b_rptr == mp->b_wptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14075
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14076
		 * The header has been consumed, so we remove the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14077
		 * zero-length mblk here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14078
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14079
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14080
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14081
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14082
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14083
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14084
	tcp->tcp_rack_cnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14085
	{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14086
		uint32_t cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14087
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14088
		cur_max = tcp->tcp_rack_cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14089
		if (tcp->tcp_rack_cnt >= cur_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14090
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14091
			 * We have more unacked data than we should - send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14092
			 * an ACK now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14093
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14094
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14095
			cur_max++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14096
			if (cur_max > tcp->tcp_rack_abs_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14097
				tcp->tcp_rack_cur_max = tcp->tcp_rack_abs_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14098
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14099
				tcp->tcp_rack_cur_max = cur_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14100
		} else if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14101
			/* We don't have an ACK timer for detached TCP. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14102
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14103
		} else if (seg_len < mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14104
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14105
			 * If we get a segment that is less than an mss, and we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14106
			 * already have unacknowledged data, and the amount
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14107
			 * unacknowledged is not a multiple of mss, then we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14108
			 * better generate an ACK now.  Otherwise, this may be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14109
			 * the tail piece of a transaction, and we would rather
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14110
			 * wait for the response.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14111
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14112
			uint32_t udif;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14113
			ASSERT((uintptr_t)(tcp->tcp_rnxt - tcp->tcp_rack) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14114
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14115
			udif = (int)(tcp->tcp_rnxt - tcp->tcp_rack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14116
			if (udif && (udif % mss))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14117
				flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14118
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14119
				flags |= TH_ACK_TIMER_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14120
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14121
			/* Start delayed ack timer */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14122
			flags |= TH_ACK_TIMER_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14123
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14124
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14125
	tcp->tcp_rnxt += seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14126
	U32_TO_ABE32(tcp->tcp_rnxt, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14128
	/* Update SACK list */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14129
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14130
		tcp_sack_remove(tcp->tcp_sack_list, tcp->tcp_rnxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14131
		    &(tcp->tcp_num_sack_blk));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14132
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14134
	if (tcp->tcp_urp_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14135
		tcp->tcp_urp_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14136
		mp = tcp->tcp_urp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14137
		tcp->tcp_urp_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14138
		/* Ready for a new signal. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14139
		tcp->tcp_urp_last_valid = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14140
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14141
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14142
		    "tcp_rput: sending exdata_ind %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14143
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14144
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14145
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14147
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14148
	 * Check for ancillary data changes compared to last segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14149
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14150
	if (tcp->tcp_ipv6_recvancillary != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14151
		mp = tcp_rput_add_ancillary(tcp, mp, &ipp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14152
		if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14153
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14156
	if (tcp->tcp_listener || tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14157
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14158
		 * Side queue inbound data until the accept happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14159
		 * tcp_accept/tcp_rput drains this when the accept happens.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14160
		 * M_DATA is queued on b_cont. Otherwise (T_OPTDATA_IND or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14161
		 * T_EXDATA_IND) it is queued on b_next.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14162
		 * XXX Make urgent data use this. Requires:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14163
		 *	Removing tcp_listener check for TH_URG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14164
		 *	Making M_PCPROTO and MARK messages skip the eager case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14165
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14166
		tcp_rcv_enqueue(tcp, mp, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14167
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14168
		if (mp->b_datap->db_type != M_DATA ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14169
		    (flags & TH_MARKNEXT_NEEDED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14170
			if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14171
				flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14172
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14173
			ASSERT(tcp->tcp_rcv_list == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14174
			    tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14175
			if (flags & TH_MARKNEXT_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14176
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14177
				(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14178
				    "tcp_rput: sending MSGMARKNEXT %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14179
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14180
				    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14181
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14182
				mp->b_flag |= MSGMARKNEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14183
				flags &= ~TH_MARKNEXT_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14184
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14185
			putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14186
			if (!canputnext(tcp->tcp_rq))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14187
				tcp->tcp_rwnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14188
		} else if (((flags & (TH_PUSH|TH_FIN)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14189
		    tcp->tcp_rcv_cnt + seg_len >= tcp->tcp_rq->q_hiwat >> 3) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14190
		    (sqp != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14191
			if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14192
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14193
				 * Enqueue the new segment first and then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14194
				 * call tcp_rcv_drain() to send all data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14195
				 * up.  The other way to do this is to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14196
				 * send all queued data up and then call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14197
				 * putnext() to send the new segment up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14198
				 * This way can remove the else part later
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14199
				 * on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14200
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14201
				 * We don't this to avoid one more call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14202
				 * canputnext() as tcp_rcv_drain() needs to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14203
				 * call canputnext().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14204
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14205
				tcp_rcv_enqueue(tcp, mp, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14206
				flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14207
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14208
				putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14209
				if (!canputnext(tcp->tcp_rq))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14210
					tcp->tcp_rwnd -= seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14211
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14212
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14213
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14214
			 * Enqueue all packets when processing an mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14215
			 * from the co queue and also enqueue normal packets.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14216
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14217
			tcp_rcv_enqueue(tcp, mp, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14218
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14219
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14220
		 * Make sure the timer is running if we have data waiting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14221
		 * for a push bit. This provides resiliency against
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14222
		 * implementations that do not correctly generate push bits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14223
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14224
		if ((sqp != NULL) && tcp->tcp_rcv_list != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14225
		    tcp->tcp_push_tid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14226
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14227
			 * The connection may be closed at this point, so don't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14228
			 * do anything for a detached tcp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14229
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14230
			if (!TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14231
				tcp->tcp_push_tid = TCP_TIMER(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14232
				    tcp_push_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14233
				    MSEC_TO_TICK(tcp_push_timer_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14234
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14235
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14236
xmit_check:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14237
	/* Is there anything left to do? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14238
	ASSERT(!(flags & TH_MARKNEXT_NEEDED));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14239
	if ((flags & (TH_REXMIT_NEEDED|TH_XMIT_NEEDED|TH_ACK_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14240
	    TH_NEED_SACK_REXMIT|TH_LIMIT_XMIT|TH_ACK_TIMER_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14241
	    TH_ORDREL_NEEDED|TH_SEND_URP_MARK)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14242
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14244
	/* Any transmit work to do and a non-zero window? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14245
	if ((flags & (TH_REXMIT_NEEDED|TH_XMIT_NEEDED|TH_NEED_SACK_REXMIT|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14246
	    TH_LIMIT_XMIT)) && tcp->tcp_swnd != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14247
		if (flags & TH_REXMIT_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14248
			uint32_t snd_size = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14250
			BUMP_MIB(&tcp_mib, tcpOutFastRetrans);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14251
			if (snd_size > mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14252
				snd_size = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14253
			if (snd_size > tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14254
				snd_size = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14255
			mp1 = tcp_xmit_mp(tcp, tcp->tcp_xmit_head, snd_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14256
			    NULL, NULL, tcp->tcp_suna, B_TRUE, &snd_size,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14257
			    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14259
			if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14260
				tcp->tcp_xmit_head->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14261
				tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14262
				BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14263
				UPDATE_MIB(&tcp_mib, tcpRetransBytes, snd_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14264
				TCP_RECORD_TRACE(tcp, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14265
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14266
				tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14267
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14268
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14269
		if (flags & TH_NEED_SACK_REXMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14270
			tcp_sack_rxmit(tcp, &flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14271
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14272
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14273
		 * For TH_LIMIT_XMIT, tcp_wput_data() is called to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14274
		 * out new segment.  Note that tcp_rexmit should not be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14275
		 * set, otherwise TH_LIMIT_XMIT should not be set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14276
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14277
		if (flags & (TH_XMIT_NEEDED|TH_LIMIT_XMIT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14278
			if (!tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14279
				tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14280
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14281
				tcp_ss_rexmit(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14282
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14283
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14284
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14285
		 * Adjust tcp_cwnd back to normal value after sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14286
		 * new data segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14287
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14288
		if (flags & TH_LIMIT_XMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14289
			tcp->tcp_cwnd -= mss << (tcp->tcp_dupack_cnt - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14290
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14291
			 * This will restart the timer.  Restarting the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14292
			 * timer is used to avoid a timeout before the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14293
			 * limited transmitted segment's ACK gets back.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14294
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14295
			if (tcp->tcp_xmit_head != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14296
				tcp->tcp_xmit_head->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14297
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14299
		/* Anything more to do? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14300
		if ((flags & (TH_ACK_NEEDED|TH_ACK_TIMER_NEEDED|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14301
		    TH_ORDREL_NEEDED|TH_SEND_URP_MARK)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14302
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14303
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14304
ack_check:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14305
	if (flags & TH_SEND_URP_MARK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14306
		ASSERT(tcp->tcp_urp_mark_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14307
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14308
		 * Send up any queued data and then send the mark message
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14309
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14310
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14311
			flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14312
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14313
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14315
		mp1 = tcp->tcp_urp_mark_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14316
		tcp->tcp_urp_mark_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14317
#ifdef DEBUG
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 14318
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14319
		    "tcp_rput: sending zero-length %s %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14320
		    ((mp1->b_flag & MSGMARKNEXT) ? "MSGMARKNEXT" :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14321
		    "MSGNOTMARKNEXT"),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14322
		    tcp_display(tcp, NULL, DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14323
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14324
		putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14325
		flags &= ~TH_SEND_URP_MARK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14326
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14327
	if (flags & TH_ACK_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14328
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14329
		 * Time to send an ack for some reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14330
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14331
		mp1 = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14332
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14333
		if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14334
			TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14335
			tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14336
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14337
			BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14338
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14339
		if (tcp->tcp_ack_tid != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14340
			(void) TCP_TIMER_CANCEL(tcp, tcp->tcp_ack_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14341
			tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14342
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14343
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14344
	if (flags & TH_ACK_TIMER_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14345
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14346
		 * Arrange for deferred ACK or push wait timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14347
		 * Start timer if it is not already running.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14348
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14349
		if (tcp->tcp_ack_tid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14350
			tcp->tcp_ack_tid = TCP_TIMER(tcp, tcp_ack_timer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14351
			    MSEC_TO_TICK(tcp->tcp_localnet ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14352
			    (clock_t)tcp_local_dack_interval :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14353
			    (clock_t)tcp_deferred_ack_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14354
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14355
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14356
	if (flags & TH_ORDREL_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14357
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14358
		 * Send up the ordrel_ind unless we are an eager guy.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14359
		 * In the eager case tcp_rsrv will do this when run
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14360
		 * after tcp_accept is done.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14361
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14362
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14363
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14364
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14365
			 * Push any mblk(s) enqueued from co processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14366
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14367
			flags |= tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14368
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14369
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14370
		if ((mp1 = mi_tpi_ordrel_ind()) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14371
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14372
			putnext(tcp->tcp_rq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14373
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14374
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14375
				 * tcp_clean_death was deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14376
				 * for T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14377
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14378
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14379
				    tcp->tcp_client_errno, 20);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14380
				tcp->tcp_deferred_clean_death =	B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14381
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14382
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14383
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14384
			 * Run the orderly release in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14385
			 * service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14386
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14387
			qenable(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14388
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14389
			 * Caveat(XXX): The machine may be so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14390
			 * overloaded that tcp_rsrv() is not scheduled
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14391
			 * until after the endpoint has transitioned
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14392
			 * to TCPS_TIME_WAIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14393
			 * and tcp_time_wait_interval expires. Then
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14394
			 * tcp_timer() will blow away state in tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14395
			 * and T_ORDREL_IND will never be delivered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14396
			 * upstream. Unlikely but potentially
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14397
			 * a problem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14398
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14399
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14400
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14401
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14402
	ASSERT(!(flags & TH_MARKNEXT_NEEDED));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14403
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14404
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14405
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14406
 * This function does PAWS protection check. Returns B_TRUE if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14407
 * segment passes the PAWS test, else returns B_FALSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14408
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14409
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14410
tcp_paws_check(tcp_t *tcp, tcph_t *tcph, tcp_opt_t *tcpoptp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14411
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14412
	uint8_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14413
	int	options;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14414
	uint8_t *up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14416
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14417
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14418
	 * If timestamp option is aligned nicely, get values inline,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14419
	 * otherwise call general routine to parse.  Only do that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14420
	 * if timestamp is the only option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14421
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14422
	if (TCP_HDR_LENGTH(tcph) == (uint32_t)TCP_MIN_HEADER_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14423
	    TCPOPT_REAL_TS_LEN &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14424
	    OK_32PTR((up = ((uint8_t *)tcph) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14425
	    TCP_MIN_HEADER_LENGTH)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14426
	    *(uint32_t *)up == TCPOPT_NOP_NOP_TSTAMP) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14427
		tcpoptp->tcp_opt_ts_val = ABE32_TO_U32((up+4));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14428
		tcpoptp->tcp_opt_ts_ecr = ABE32_TO_U32((up+8));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14429
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14430
		options = TCP_OPT_TSTAMP_PRESENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14431
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14432
		if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14433
			tcpoptp->tcp = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14434
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14435
			tcpoptp->tcp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14436
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14437
		options = tcp_parse_options(tcph, tcpoptp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14438
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14440
	if (options & TCP_OPT_TSTAMP_PRESENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14441
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14442
		 * Do PAWS per RFC 1323 section 4.2.  Accept RST
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14443
		 * regardless of the timestamp, page 18 RFC 1323.bis.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14444
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14445
		if ((flags & TH_RST) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14446
		    TSTMP_LT(tcpoptp->tcp_opt_ts_val,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14447
		    tcp->tcp_ts_recent)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14448
			if (TSTMP_LT(lbolt64, tcp->tcp_last_rcv_lbolt +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14449
			    PAWS_TIMEOUT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14450
				/* This segment is not acceptable. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14451
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14452
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14453
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14454
				 * Connection has been idle for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14455
				 * too long.  Reset the timestamp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14456
				 * and assume the segment is valid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14457
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14458
				tcp->tcp_ts_recent =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14459
				    tcpoptp->tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14460
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14461
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14462
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14463
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14464
		 * If we don't get a timestamp on every packet, we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14465
		 * figure we can't really trust 'em, so we stop sending
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14466
		 * and parsing them.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14467
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14468
		tcp->tcp_snd_ts_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14470
		tcp->tcp_hdr_len -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14471
		tcp->tcp_tcp_hdr_len -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14472
		tcp->tcp_tcph->th_offset_and_rsrvd[0] -= (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14473
		tcp_mss_set(tcp, tcp->tcp_mss + TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14474
		if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14475
			ASSERT(tcp->tcp_sack_info != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14476
			tcp->tcp_max_sack_blk = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14477
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14478
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14479
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14480
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14481
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14482
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14483
 * Attach ancillary data to a received TCP segments for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14484
 * ancillary pieces requested by the application that are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14485
 * different than they were in the previous data segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14486
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14487
 * Save the "current" values once memory allocation is ok so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14488
 * when memory allocation fails we can just wait for the next data segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14489
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14490
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14491
tcp_rput_add_ancillary(tcp_t *tcp, mblk_t *mp, ip6_pkt_t *ipp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14492
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14493
	struct T_optdata_ind *todi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14494
	int optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14495
	uchar_t *optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14496
	struct T_opthdr *toh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14497
	uint_t addflag;	/* Which pieces to add */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14498
	mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14500
	optlen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14501
	addflag = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14502
	/* If app asked for pktinfo and the index has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14503
	if ((ipp->ipp_fields & IPPF_IFINDEX) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14504
	    ipp->ipp_ifindex != tcp->tcp_recvifindex &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14505
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14506
		optlen += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14507
		    sizeof (struct in6_pktinfo);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14508
		addflag |= TCP_IPV6_RECVPKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14509
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14510
	/* If app asked for hoplimit and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14511
	if ((ipp->ipp_fields & IPPF_HOPLIMIT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14512
	    ipp->ipp_hoplimit != tcp->tcp_recvhops &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14513
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPLIMIT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14514
		optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14515
		addflag |= TCP_IPV6_RECVHOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14516
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14517
	/* If app asked for tclass and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14518
	if ((ipp->ipp_fields & IPPF_TCLASS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14519
	    ipp->ipp_tclass != tcp->tcp_recvtclass &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14520
	    (tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVTCLASS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14521
		optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14522
		addflag |= TCP_IPV6_RECVTCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14523
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14524
	/* If app asked for hopbyhop headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14525
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVHOPOPTS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14526
	    tcp_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14527
		(ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14528
		ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14529
		optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14530
		addflag |= TCP_IPV6_RECVHOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14531
		if (!tcp_allocbuf((void **)&tcp->tcp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14532
		    &tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14533
		    (ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14534
		    ipp->ipp_hopopts, ipp->ipp_hopoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14535
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14536
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14537
	/* If app asked for dst headers before routing headers ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14538
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTDSTOPTS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14539
	    tcp_cmpbuf(tcp->tcp_rtdstopts, tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14540
		(ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14541
		ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14542
		optlen += sizeof (struct T_opthdr) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14543
		    ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14544
		addflag |= TCP_IPV6_RECVRTDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14545
		if (!tcp_allocbuf((void **)&tcp->tcp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14546
		    &tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14547
		    (ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14548
		    ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14549
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14550
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14551
	/* If app asked for routing headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14552
	if ((tcp->tcp_ipv6_recvancillary & TCP_IPV6_RECVRTHDR) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14553
	    tcp_cmpbuf(tcp->tcp_rthdr, tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14554
		(ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14555
		ipp->ipp_rthdr, ipp->ipp_rthdrlen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14556
		optlen += sizeof (struct T_opthdr) + ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14557
		addflag |= TCP_IPV6_RECVRTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14558
		if (!tcp_allocbuf((void **)&tcp->tcp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14559
		    &tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14560
		    (ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14561
		    ipp->ipp_rthdr, ipp->ipp_rthdrlen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14562
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14563
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14564
	/* If app asked for dest headers and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14565
	if ((tcp->tcp_ipv6_recvancillary &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14566
		(TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14567
	    tcp_cmpbuf(tcp->tcp_dstopts, tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14568
		(ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14569
		ipp->ipp_dstopts, ipp->ipp_dstoptslen)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14570
		optlen += sizeof (struct T_opthdr) + ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14571
		addflag |= TCP_IPV6_RECVDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14572
		if (!tcp_allocbuf((void **)&tcp->tcp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14573
		    &tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14574
		    (ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14575
		    ipp->ipp_dstopts, ipp->ipp_dstoptslen))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14576
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14577
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14579
	if (optlen == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14580
		/* Nothing to add */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14581
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14582
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14583
	mp1 = allocb(sizeof (struct T_optdata_ind) + optlen, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14584
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14585
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14586
		 * Defer sending ancillary data until the next TCP segment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14587
		 * arrives.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14588
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14589
		return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14590
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14591
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14592
	mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14593
	mp->b_wptr += sizeof (*todi) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14594
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14595
	todi = (struct T_optdata_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14596
	todi->PRIM_type = T_OPTDATA_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14597
	todi->DATA_flag = 1;	/* MORE data */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14598
	todi->OPT_length = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14599
	todi->OPT_offset = sizeof (*todi);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14600
	optptr = (uchar_t *)&todi[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14601
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14602
	 * If app asked for pktinfo and the index has changed ...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14603
	 * Note that the local address never changes for the connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14604
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14605
	if (addflag & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14606
		struct in6_pktinfo *pkti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14608
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14609
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14610
		toh->name = IPV6_PKTINFO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14611
		toh->len = sizeof (*toh) + sizeof (*pkti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14612
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14613
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14614
		pkti = (struct in6_pktinfo *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14615
		if (tcp->tcp_ipversion == IPV6_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14616
			pkti->ipi6_addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14617
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14618
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14619
			    &pkti->ipi6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14620
		pkti->ipi6_ifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14621
		optptr += sizeof (*pkti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14622
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14623
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14624
		tcp->tcp_recvifindex = ipp->ipp_ifindex;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14625
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14626
	/* If app asked for hoplimit and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14627
	if (addflag & TCP_IPV6_RECVHOPLIMIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14628
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14629
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14630
		toh->name = IPV6_HOPLIMIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14631
		toh->len = sizeof (*toh) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14632
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14633
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14634
		*(uint_t *)optptr = ipp->ipp_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14635
		optptr += sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14636
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14637
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14638
		tcp->tcp_recvhops = ipp->ipp_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14639
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14640
	/* If app asked for tclass and it has changed ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14641
	if (addflag & TCP_IPV6_RECVTCLASS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14642
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14643
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14644
		toh->name = IPV6_TCLASS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14645
		toh->len = sizeof (*toh) + sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14646
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14647
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14648
		*(uint_t *)optptr = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14649
		optptr += sizeof (uint_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14650
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14651
		/* Save as "last" value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14652
		tcp->tcp_recvtclass = ipp->ipp_tclass;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14653
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14654
	if (addflag & TCP_IPV6_RECVHOPOPTS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14655
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14656
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14657
		toh->name = IPV6_HOPOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14658
		toh->len = sizeof (*toh) + ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14659
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14660
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14661
		bcopy(ipp->ipp_hopopts, optptr, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14662
		optptr += ipp->ipp_hopoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14663
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14664
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14665
		tcp_savebuf((void **)&tcp->tcp_hopopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14666
		    &tcp->tcp_hopoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14667
		    (ipp->ipp_fields & IPPF_HOPOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14668
		    ipp->ipp_hopopts, ipp->ipp_hopoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14669
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14670
	if (addflag & TCP_IPV6_RECVRTDSTOPTS) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14671
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14672
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14673
		toh->name = IPV6_RTHDRDSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14674
		toh->len = sizeof (*toh) + ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14675
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14676
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14677
		bcopy(ipp->ipp_rtdstopts, optptr, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14678
		optptr += ipp->ipp_rtdstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14679
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14680
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14681
		tcp_savebuf((void **)&tcp->tcp_rtdstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14682
		    &tcp->tcp_rtdstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14683
		    (ipp->ipp_fields & IPPF_RTDSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14684
		    ipp->ipp_rtdstopts, ipp->ipp_rtdstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14685
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14686
	if (addflag & TCP_IPV6_RECVRTHDR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14687
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14688
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14689
		toh->name = IPV6_RTHDR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14690
		toh->len = sizeof (*toh) + ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14691
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14692
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14693
		bcopy(ipp->ipp_rthdr, optptr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14694
		optptr += ipp->ipp_rthdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14695
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14696
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14697
		tcp_savebuf((void **)&tcp->tcp_rthdr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14698
		    &tcp->tcp_rthdrlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14699
		    (ipp->ipp_fields & IPPF_RTHDR),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14700
		    ipp->ipp_rthdr, ipp->ipp_rthdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14701
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14702
	if (addflag & (TCP_IPV6_RECVDSTOPTS | TCP_OLD_IPV6_RECVDSTOPTS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14703
		toh = (struct T_opthdr *)optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14704
		toh->level = IPPROTO_IPV6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14705
		toh->name = IPV6_DSTOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14706
		toh->len = sizeof (*toh) + ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14707
		toh->status = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14708
		optptr += sizeof (*toh);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14709
		bcopy(ipp->ipp_dstopts, optptr, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14710
		optptr += ipp->ipp_dstoptslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14711
		ASSERT(OK_32PTR(optptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14712
		/* Save as last value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14713
		tcp_savebuf((void **)&tcp->tcp_dstopts,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14714
		    &tcp->tcp_dstoptslen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14715
		    (ipp->ipp_fields & IPPF_DSTOPTS),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14716
		    ipp->ipp_dstopts, ipp->ipp_dstoptslen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14717
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14718
	ASSERT(optptr == mp->b_wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14719
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14720
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14723
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14724
 * Handle a *T_BIND_REQ that has failed either due to a T_ERROR_ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14725
 * or a "bad" IRE detected by tcp_adapt_ire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14726
 * We can't tell if the failure was due to the laddr or the faddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14727
 * thus we clear out all addresses and ports.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14728
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14729
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14730
tcp_bind_failed(tcp_t *tcp, mblk_t *mp, int error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14731
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14732
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14733
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14734
	struct T_error_ack *tea;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14735
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14736
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14738
	ASSERT(mp->b_datap->db_type == M_PCPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14739
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14740
	if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14741
		freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14742
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14743
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14744
	tea = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14745
	switch (tea->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14746
	case T_BIND_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14747
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14748
		 * Need to unbind with classifier since we were just told that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14749
		 * our bind succeeded.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14750
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14751
		tcp->tcp_hard_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14752
		tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14754
		ipcl_hash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14755
		/* Reuse the mblk if possible */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14756
		ASSERT(mp->b_datap->db_lim - mp->b_datap->db_base >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14757
			sizeof (*tea));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14758
		mp->b_rptr = mp->b_datap->db_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14759
		mp->b_wptr = mp->b_rptr + sizeof (*tea);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14760
		tea = (struct T_error_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14761
		tea->PRIM_type = T_ERROR_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14762
		tea->TLI_error = TSYSERR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14763
		tea->UNIX_error = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14764
		if (tcp->tcp_state >= TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14765
			tea->ERROR_prim = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14766
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14767
			tea->ERROR_prim = O_T_BIND_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14768
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14769
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14771
	case T_ERROR_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14772
		if (tcp->tcp_state >= TCPS_SYN_SENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14773
			tea->ERROR_prim = T_CONN_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14774
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14775
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14776
		panic("tcp_bind_failed: unexpected TPI type");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14777
		/*NOTREACHED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14778
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14779
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14780
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14781
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14782
		tcp->tcp_ipha->ipha_src = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14783
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14784
		V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14785
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14786
	 * Copy of the src addr. in tcp_t is needed since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14787
	 * the lookup funcs. can only look at tcp_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14788
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14789
	V6_SET_ZERO(tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14791
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14792
	tcph->th_lport[0] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14793
	tcph->th_lport[1] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14794
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14795
	bzero(&connp->u_port, sizeof (connp->u_port));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14796
	/* blow away saved option results if any */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14797
	if (tcp->tcp_conn.tcp_opts_conn_req != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14798
		tcp_close_mpp(&tcp->tcp_conn.tcp_opts_conn_req);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14799
487
511557ecdec8 6174818 Sun-Fire,serengeti system panicked during lckbugs testing in s10_69
rshoaib
parents: 269
diff changeset
 14800
	conn_delete_ire(tcp->tcp_connp, NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14801
	putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14802
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14803
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14804
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14805
 * tcp_rput_other is called by tcp_rput to handle everything other than M_DATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14806
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14807
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14808
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14809
tcp_rput_other(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14810
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14811
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14812
	uchar_t	*rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14813
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14814
	struct T_error_ack *tea;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14815
	uint32_t mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14816
	mblk_t *syn_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14817
	mblk_t *mdti;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14818
	int	retval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14819
	mblk_t *ire_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14821
	switch (mp->b_datap->db_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14822
	case M_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14823
	case M_PCPROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14824
		ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14825
		if ((mp->b_wptr - rptr) < sizeof (t_scalar_t))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14826
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14827
		tea = (struct T_error_ack *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14828
		switch (tea->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14829
		case T_BIND_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14830
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14831
			 * Adapt Multidata information, if any.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14832
			 * following tcp_mdt_update routine will free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14833
			 * the message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14834
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14835
			if ((mdti = tcp_mdt_info_mp(mp)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14836
				tcp_mdt_update(tcp, &((ip_mdt_info_t *)mdti->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14837
				    b_rptr)->mdt_capab, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14838
				freemsg(mdti);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14839
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14840
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14841
			/* Get the IRE, if we had requested for it */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14842
			ire_mp = tcp_ire_mp(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14844
			if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14845
				tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14846
				tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14847
				CL_INET_CONNECT(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14848
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14849
				if (ire_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14850
					freeb(ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14851
				goto after_syn_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14852
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14854
			retval = tcp_adapt_ire(tcp, ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14855
			if (ire_mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14856
				freeb(ire_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14857
			if (retval == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14858
				tcp_bind_failed(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14859
				    (int)((tcp->tcp_state >= TCPS_SYN_SENT) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14860
				    ENETUNREACH : EADDRNOTAVAIL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14861
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14862
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14863
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14864
			 * Don't let an endpoint connect to itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14865
			 * Also checked in tcp_connect() but that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14866
			 * check can't handle the case when the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14867
			 * local IP address is INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14868
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14869
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14870
				if ((tcp->tcp_ipha->ipha_dst ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14871
				    tcp->tcp_ipha->ipha_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14872
				    (BE16_EQL(tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14873
				    tcp->tcp_tcph->th_fport))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14874
					tcp_bind_failed(tcp, mp, EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14875
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14876
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14877
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14878
				if (IN6_ARE_ADDR_EQUAL(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14879
				    &tcp->tcp_ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14880
				    &tcp->tcp_ip6h->ip6_src) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14881
				    (BE16_EQL(tcp->tcp_tcph->th_lport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14882
				    tcp->tcp_tcph->th_fport))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14883
					tcp_bind_failed(tcp, mp, EADDRNOTAVAIL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14884
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14885
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14886
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14887
			ASSERT(tcp->tcp_state == TCPS_SYN_SENT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14888
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14889
			 * This should not be possible!  Just for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14890
			 * defensive coding...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14891
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14892
			if (tcp->tcp_state != TCPS_SYN_SENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14893
				goto after_syn_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14894
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14895
			ASSERT(q == tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14896
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14897
			 * tcp_adapt_ire() does not adjust
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14898
			 * for TCP/IP header length.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14899
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14900
			mss = tcp->tcp_mss - tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14901
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14902
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14903
			 * Just make sure our rwnd is at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14904
			 * least tcp_recv_hiwat_mss * MSS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14905
			 * large, and round up to the nearest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14906
			 * MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14907
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14908
			 * We do the round up here because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14909
			 * we need to get the interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14910
			 * MTU first before we can do the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14911
			 * round up.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14912
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14913
			tcp->tcp_rwnd = MAX(MSS_ROUNDUP(tcp->tcp_rwnd, mss),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14914
			    tcp_recv_hiwat_minmss * mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14915
			q->q_hiwat = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14916
			tcp_set_ws_value(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14917
			U32_TO_ABE16((tcp->tcp_rwnd >> tcp->tcp_rcv_ws),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14918
			    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14919
			if (tcp->tcp_rcv_ws > 0 || tcp_wscale_always)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14920
				tcp->tcp_snd_ws_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14921
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14922
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14923
			 * Set tcp_snd_ts_ok to true
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14924
			 * so that tcp_xmit_mp will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14925
			 * include the timestamp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14926
			 * option in the SYN segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14927
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14928
			if (tcp_tstamp_always ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14929
			    (tcp->tcp_rcv_ws && tcp_tstamp_if_wscale)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14930
				tcp->tcp_snd_ts_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14931
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14932
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14933
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14934
			 * tcp_snd_sack_ok can be set in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14935
			 * tcp_adapt_ire() if the sack metric
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14936
			 * is set.  So check it here also.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14937
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14938
			if (tcp_sack_permitted == 2 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14939
			    tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14940
				if (tcp->tcp_sack_info == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14941
					tcp->tcp_sack_info =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14942
					kmem_cache_alloc(tcp_sack_info_cache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14943
					    KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14944
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14945
				tcp->tcp_snd_sack_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14946
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14947
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14948
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14949
			 * Should we use ECN?  Note that the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14950
			 * default value (SunOS 5.9) of tcp_ecn_permitted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14951
			 * is 1.  The reason for doing this is that there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14952
			 * are equipments out there that will drop ECN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14953
			 * enabled IP packets.  Setting it to 1 avoids
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14954
			 * compatibility problems.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14955
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14956
			if (tcp_ecn_permitted == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14957
				tcp->tcp_ecn_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14959
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14960
			syn_mp = tcp_xmit_mp(tcp, NULL, 0, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14961
			    tcp->tcp_iss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14962
			if (syn_mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14963
				cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14964
				pid_t pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14966
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14967
				 * Obtain the credential from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14968
				 * thread calling connect(); the credential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14969
				 * lives on in the second mblk which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14970
				 * originated from T_CONN_REQ and is echoed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14971
				 * with the T_BIND_ACK from ip.  If none
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14972
				 * can be found, default to the creator
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14973
				 * of the socket.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14974
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14975
				if (mp->b_cont == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14976
				    (cr = DB_CRED(mp->b_cont)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14977
					cr = tcp->tcp_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14978
					pid = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14979
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14980
					pid = DB_CPID(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14981
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14983
				TCP_RECORD_TRACE(tcp, syn_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14984
				    TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14985
				mblk_setcred(syn_mp, cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14986
				DB_CPID(syn_mp) = pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14987
				tcp_send_data(tcp, tcp->tcp_wq, syn_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14988
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14989
		after_syn_sent:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14990
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14991
			 * A trailer mblk indicates a waiting client upstream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14992
			 * We complete here the processing begun in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14993
			 * either tcp_bind() or tcp_connect() by passing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14994
			 * upstream the reply message they supplied.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14995
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14996
			mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14997
			mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14998
			freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 14999
			if (mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15000
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15001
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15002
		case T_ERROR_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15003
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15004
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15005
				    SL_TRACE|SL_ERROR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15006
				    "tcp_rput_other: case T_ERROR_ACK, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15007
				    "ERROR_prim == %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15008
				    tea->ERROR_prim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15009
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15010
			switch (tea->ERROR_prim) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15011
			case O_T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15012
			case T_BIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15013
				tcp_bind_failed(tcp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15014
				    (int)((tcp->tcp_state >= TCPS_SYN_SENT) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15015
				    ENETUNREACH : EADDRNOTAVAIL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15016
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15017
			case T_UNBIND_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15018
				tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15019
				tcp->tcp_hard_bound = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15020
				if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15021
					freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15022
					mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15023
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15024
				if (tcp->tcp_unbind_pending)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15025
					tcp->tcp_unbind_pending = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15026
				else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15027
					/* From tcp_ip_unbind() - free */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15028
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15029
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15030
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15031
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15032
			case T_SVR4_OPTMGMT_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15033
				if (tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15034
					/* T_OPTMGMT_REQ generated by TCP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15035
					printf("T_SVR4_OPTMGMT_REQ failed "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15036
					    "%d/%d - dropped (cnt %d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15037
					    tea->TLI_error, tea->UNIX_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15038
					    tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15039
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15040
					tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15041
					return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15042
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15043
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15044
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15045
			if (tea->ERROR_prim == T_SVR4_OPTMGMT_REQ &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15046
			    tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15047
				printf("T_SVR4_OPTMGMT_REQ failed %d/%d "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15048
				    "- dropped (cnt %d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15049
				    tea->TLI_error, tea->UNIX_error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15050
				    tcp->tcp_drop_opt_ack_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15051
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15052
				tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15053
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15054
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15055
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15056
		case T_OPTMGMT_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15057
			if (tcp->tcp_drop_opt_ack_cnt > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15058
				/* T_OPTMGMT_REQ generated by TCP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15059
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15060
				tcp->tcp_drop_opt_ack_cnt--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15061
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15062
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15063
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15064
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15065
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15066
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15067
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15068
	case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15069
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15070
		 * ICMP messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15071
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15072
		tcp_icmp_error(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15073
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15074
	case M_FLUSH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15075
		if (*rptr & FLUSHR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15076
			flushq(q, FLUSHDATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15077
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15078
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15079
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15080
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15081
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15082
	 * Make sure we set this bit before sending the ACK for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15083
	 * bind. Otherwise accept could possibly run and free
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15084
	 * this tcp struct.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15085
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15086
	putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15087
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15088
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15089
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15090
 * Called as the result of a qbufcall or a qtimeout to remedy a failure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15091
 * to allocate a T_ordrel_ind in tcp_rsrv().  qenable(q) will make
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15092
 * tcp_rsrv() try again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15093
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15094
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15095
tcp_ordrel_kick(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15096
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15097
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15098
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15100
	tcp->tcp_ordrelid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15101
	tcp->tcp_timeout = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15102
	if (!TCP_IS_DETACHED(tcp) && tcp->tcp_rq != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15103
	    tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15104
		qenable(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15105
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15106
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15107
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15108
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15109
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15110
tcp_rsrv_input(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15111
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15112
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15113
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15114
	queue_t	*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15115
	uint_t	thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15117
	freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15118
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15119
	TCP_STAT(tcp_rsrv_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15121
	if (TCP_IS_DETACHED(tcp) || q == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15122
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15125
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15126
		tcp_t *peer_tcp = tcp->tcp_loopback_peer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15128
		ASSERT(tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15129
		ASSERT(peer_tcp != NULL && peer_tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15130
		ASSERT(peer_tcp->tcp_loopback_peer == tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15131
		ASSERT(!TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15132
		ASSERT(tcp->tcp_connp->conn_sqp ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15133
		    peer_tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15134
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15135
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15136
		 * Normally we would not get backenabled in synchronous
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15137
		 * streams mode, but in case this happens, we need to stop
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15138
		 * synchronous streams temporarily to prevent a race with
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15139
		 * tcp_fuse_rrw() or tcp_fuse_rinfop().  It is safe to access
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15140
		 * tcp_rcv_list here because those entry points will return
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15141
		 * right away when synchronous streams is stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15142
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15143
		TCP_FUSE_SYNCSTR_STOP(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15144
		if (tcp->tcp_rcv_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15145
			(void) tcp_rcv_drain(tcp->tcp_rq, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15147
		tcp_clrqfull(peer_tcp);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15148
		TCP_FUSE_SYNCSTR_RESUME(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15149
		TCP_STAT(tcp_fusion_backenabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15150
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15151
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15152
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15153
	if (canputnext(q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15154
		tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15155
		thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15156
		    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15157
		thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15158
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15159
		 * Send back a window update immediately if TCP is above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15160
		 * ESTABLISHED state and the increase of the rcv window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15161
		 * that the other side knows is at least 1 MSS after flow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15162
		 * control is lifted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15163
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15164
		if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15165
		    (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15166
			tcp_xmit_ctl(NULL, tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15167
			    (tcp->tcp_swnd == 0) ? tcp->tcp_suna :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15168
			    tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15169
			BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15170
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15171
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15172
	/* Handle a failure to allocate a T_ORDREL_IND here */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15173
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15174
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15175
		if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15176
			(void) tcp_rcv_drain(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15177
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15178
		ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15179
		mp = mi_tpi_ordrel_ind();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15180
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15181
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15182
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15183
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15184
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15185
				 * tcp_clean_death was deferred for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15186
				 * T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15187
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15188
				tcp->tcp_deferred_clean_death = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15189
				(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15190
				    tcp->tcp_client_errno, 22);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15191
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15192
		} else if (!tcp->tcp_timeout && tcp->tcp_ordrelid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15193
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15194
			 * If there isn't already a timer running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15195
			 * start one.  Use a 4 second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15196
			 * timer as a fallback since it can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15197
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15198
			tcp->tcp_timeout = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15199
			tcp->tcp_ordrelid = TCP_TIMER(tcp, tcp_ordrel_kick,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15200
			    MSEC_TO_TICK(4000));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15201
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15202
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15203
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15204
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15205
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15206
 * The read side service routine is called mostly when we get back-enabled as a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15207
 * result of flow control relief.  Since we don't actually queue anything in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15208
 * TCP, we have no data to send out of here.  What we do is clear the receive
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15209
 * window, and send out a window update.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15210
 * This routine is also called to drive an orderly release message upstream
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15211
 * if the attempt in tcp_rput failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15212
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15213
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15214
tcp_rsrv(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15215
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15216
	conn_t *connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15217
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15218
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15219
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15220
	/* No code does a putq on the read side */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15221
	ASSERT(q->q_first == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15223
	/* Nothing to do for the default queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15224
	if (q == tcp_g_q) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15225
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15226
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15228
	mp = allocb(0, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15229
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15230
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15231
		 * We are under memory pressure. Return for now and we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15232
		 * we will be called again later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15233
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15234
		if (!tcp->tcp_timeout && tcp->tcp_ordrelid == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15235
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15236
			 * If there isn't already a timer running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15237
			 * start one.  Use a 4 second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15238
			 * timer as a fallback since it can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15239
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15240
			tcp->tcp_timeout = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15241
			tcp->tcp_ordrelid = TCP_TIMER(tcp, tcp_ordrel_kick,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15242
			    MSEC_TO_TICK(4000));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15243
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15244
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15245
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15246
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15247
	squeue_enter(connp->conn_sqp, mp, tcp_rsrv_input, connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15248
	    SQTAG_TCP_RSRV);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15249
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15250
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15251
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15252
 * tcp_rwnd_set() is called to adjust the receive window to a desired value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15253
 * We do not allow the receive window to shrink.  After setting rwnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15254
 * set the flow control hiwat of the stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15255
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15256
 * This function is called in 2 cases:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15257
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15258
 * 1) Before data transfer begins, in tcp_accept_comm() for accepting a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15259
 *    connection (passive open) and in tcp_rput_data() for active connect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15260
 *    This is called after tcp_mss_set() when the desired MSS value is known.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15261
 *    This makes sure that our window size is a mutiple of the other side's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15262
 *    MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15263
 * 2) Handling SO_RCVBUF option.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15264
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15265
 * It is ASSUMED that the requested size is a multiple of the current MSS.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15266
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15267
 * XXX - Should allow a lower rwnd than tcp_recv_hiwat_minmss * mss if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15268
 * user requests so.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15269
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15270
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15271
tcp_rwnd_set(tcp_t *tcp, uint32_t rwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15272
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15273
	uint32_t	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15274
	uint32_t	old_max_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15275
	uint32_t	max_transmittable_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15276
	boolean_t	tcp_detached = TCP_IS_DETACHED(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15277
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15278
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15279
		size_t sth_hiwat;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15280
		tcp_t *peer_tcp = tcp->tcp_loopback_peer;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15281
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15282
		ASSERT(peer_tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15283
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15284
		 * Record the stream head's high water mark for
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15285
		 * this endpoint; this is used for flow-control
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15286
		 * purposes in tcp_fuse_output().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15287
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15288
		sth_hiwat = tcp_fuse_set_rcv_hiwat(tcp, rwnd);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15289
		if (!tcp_detached)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15290
			(void) mi_set_sth_hiwat(tcp->tcp_rq, sth_hiwat);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15291
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15292
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15293
		 * In the fusion case, the maxpsz stream head value of
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15294
		 * our peer is set according to its send buffer size
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15295
		 * and our receive buffer size; since the latter may
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15296
		 * have changed we need to update the peer's maxpsz.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15297
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15298
		(void) tcp_maxpsz_set(peer_tcp, B_TRUE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15299
		return (rwnd);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15300
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15301
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15302
	if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15303
		old_max_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15304
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15305
		old_max_rwnd = tcp->tcp_rq->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15307
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15308
	 * Insist on a receive window that is at least
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15309
	 * tcp_recv_hiwat_minmss * MSS (default 4 * MSS) to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15310
	 * funny TCP interactions of Nagle algorithm, SWS avoidance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15311
	 * and delayed acknowledgement.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15312
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15313
	rwnd = MAX(rwnd, tcp_recv_hiwat_minmss * mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15315
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15316
	 * If window size info has already been exchanged, TCP should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15317
	 * shrink the window.  Shrinking window is doable if done carefully.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15318
	 * We may add that support later.  But so far there is not a real
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15319
	 * need to do that.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15320
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15321
	if (rwnd < old_max_rwnd && tcp->tcp_state > TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15322
		/* MSS may have changed, do a round up again. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15323
		rwnd = MSS_ROUNDUP(old_max_rwnd, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15324
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15326
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15327
	 * tcp_rcv_ws starts with TCP_MAX_WINSHIFT so the following check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15328
	 * can be applied even before the window scale option is decided.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15329
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15330
	max_transmittable_rwnd = TCP_MAXWIN << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15331
	if (rwnd > max_transmittable_rwnd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15332
		rwnd = max_transmittable_rwnd -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15333
		    (max_transmittable_rwnd % mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15334
		if (rwnd < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15335
			rwnd = max_transmittable_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15336
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15337
		 * If we're over the limit we may have to back down tcp_rwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15338
		 * The increment below won't work for us. So we set all three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15339
		 * here and the increment below will have no effect.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15340
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15341
		tcp->tcp_rwnd = old_max_rwnd = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15342
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15343
	if (tcp->tcp_localnet) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15344
		tcp->tcp_rack_abs_max =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15345
		    MIN(tcp_local_dacks_max, rwnd / mss / 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15346
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15347
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15348
		 * For a remote host on a different subnet (through a router),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15349
		 * we ack every other packet to be conforming to RFC1122.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15350
		 * tcp_deferred_acks_max is default to 2.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15351
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15352
		tcp->tcp_rack_abs_max =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15353
		    MIN(tcp_deferred_acks_max, rwnd / mss / 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15354
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15355
	if (tcp->tcp_rack_cur_max > tcp->tcp_rack_abs_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15356
		tcp->tcp_rack_cur_max = tcp->tcp_rack_abs_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15357
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15358
		tcp->tcp_rack_cur_max = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15359
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15360
	 * Increment the current rwnd by the amount the maximum grew (we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15361
	 * can not overwrite it since we might be in the middle of a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15362
	 * connection.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15363
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15364
	tcp->tcp_rwnd += rwnd - old_max_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15365
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws, tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15366
	if ((tcp->tcp_rcv_ws > 0) && rwnd > tcp->tcp_cwnd_max)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15367
		tcp->tcp_cwnd_max = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15369
	if (tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15370
		return (rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15371
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15372
	 * We set the maximum receive window into rq->q_hiwat.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15373
	 * This is not actually used for flow control.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15374
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15375
	tcp->tcp_rq->q_hiwat = rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15376
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15377
	 * Set the Stream head high water mark. This doesn't have to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15378
	 * here, since we are simply using default values, but we would
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15379
	 * prefer to choose these values algorithmically, with a likely
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15380
	 * relationship to rwnd.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15381
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15382
	(void) mi_set_sth_hiwat(tcp->tcp_rq, MAX(rwnd, tcp_sth_rcv_hiwat));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15383
	return (rwnd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15384
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15386
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15387
 * Return SNMP stuff in buffer in mpdata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15388
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15389
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15390
tcp_snmp_get(queue_t *q, mblk_t *mpctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15391
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15392
	mblk_t			*mpdata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15393
	mblk_t			*mp_conn_ctl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15394
	mblk_t			*mp_conn_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15395
	mblk_t			*mp6_conn_ctl = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15396
	mblk_t			*mp6_conn_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15397
	mblk_t			*mp_conn_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15398
	mblk_t			*mp6_conn_tail = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15399
	struct opthdr		*optp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15400
	mib2_tcpConnEntry_t	tce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15401
	mib2_tcp6ConnEntry_t	tce6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15402
	connf_t			*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15403
	conn_t			*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15404
	int			i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15405
	boolean_t 		ispriv;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15406
	zoneid_t 		zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15407
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15408
	if (mpctl == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15409
	    (mpdata = mpctl->b_cont) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15410
	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15411
	    (mp6_conn_ctl = copymsg(mpctl)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15412
		if (mp_conn_ctl != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15413
			freemsg(mp_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15414
		if (mp6_conn_ctl != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15415
			freemsg(mp6_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15416
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15417
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15418
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15419
	/* build table of connections -- need count in fixed part */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15420
	mp_conn_data = mp_conn_ctl->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15421
	mp6_conn_data = mp6_conn_ctl->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15422
	SET_MIB(tcp_mib.tcpRtoAlgorithm, 4);   /* vanj */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15423
	SET_MIB(tcp_mib.tcpRtoMin, tcp_rexmit_interval_min);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15424
	SET_MIB(tcp_mib.tcpRtoMax, tcp_rexmit_interval_max);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15425
	SET_MIB(tcp_mib.tcpMaxConn, -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15426
	SET_MIB(tcp_mib.tcpCurrEstab, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15428
	ispriv =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15429
	    secpolicy_net_config((Q_TO_CONN(q))->conn_cred, B_TRUE) == 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15430
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15432
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15433
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15434
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15435
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15436
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15437
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15438
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15439
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15440
			tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15442
			if (connp->conn_zoneid != zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15443
				continue;	/* not in this zone */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15444
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15445
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15446
			UPDATE_MIB(&tcp_mib, tcpInSegs, tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15447
			tcp->tcp_ibsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15448
			UPDATE_MIB(&tcp_mib, tcpOutSegs, tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15449
			tcp->tcp_obsegs = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15450
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15451
			tce6.tcp6ConnState = tce.tcpConnState =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15452
			    tcp_snmp_state(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15453
			if (tce.tcpConnState == MIB2_TCP_established ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15454
			    tce.tcpConnState == MIB2_TCP_closeWait)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15455
				BUMP_MIB(&tcp_mib, tcpCurrEstab);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15456
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15457
			/* Create a message to report on IPv6 entries */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15458
			if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15459
			tce6.tcp6ConnLocalAddress = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15460
			tce6.tcp6ConnRemAddress = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15461
			tce6.tcp6ConnLocalPort = ntohs(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15462
			tce6.tcp6ConnRemPort = ntohs(tcp->tcp_fport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15463
			tce6.tcp6ConnIfIndex = tcp->tcp_bound_if;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15464
			/* Don't want just anybody seeing these... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15465
			if (ispriv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15466
				tce6.tcp6ConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15467
				    tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15468
				tce6.tcp6ConnEntryInfo.ce_suna =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15469
				    tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15470
				tce6.tcp6ConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15471
				    tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15472
				tce6.tcp6ConnEntryInfo.ce_rack =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15473
				    tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15474
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15475
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15476
				 * Netstat, unfortunately, uses this to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15477
				 * get send/receive queue sizes.  How to fix?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15478
				 * Why not compute the difference only?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15479
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15480
				tce6.tcp6ConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15481
				    tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15482
				tce6.tcp6ConnEntryInfo.ce_suna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15483
				tce6.tcp6ConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15484
				    tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15485
				tce6.tcp6ConnEntryInfo.ce_rack = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15486
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15488
			tce6.tcp6ConnEntryInfo.ce_swnd = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15489
			tce6.tcp6ConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15490
			tce6.tcp6ConnEntryInfo.ce_rto =  tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15491
			tce6.tcp6ConnEntryInfo.ce_mss =  tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15492
			tce6.tcp6ConnEntryInfo.ce_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15493
			(void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15494
			    (char *)&tce6, sizeof (tce6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15495
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15496
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15497
			 * Create an IPv4 table entry for IPv4 entries and also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15498
			 * for IPv6 entries which are bound to in6addr_any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15499
			 * but don't have IPV6_V6ONLY set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15500
			 * (i.e. anything an IPv4 peer could connect to)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15501
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15502
			if (tcp->tcp_ipversion == IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15503
			    (tcp->tcp_state <= TCPS_LISTEN &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15504
			    !tcp->tcp_connp->conn_ipv6_v6only &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15505
			    IN6_IS_ADDR_UNSPECIFIED(&tcp->tcp_ip_src_v6))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15506
				if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15507
					tce.tcpConnRemAddress = INADDR_ANY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15508
					tce.tcpConnLocalAddress = INADDR_ANY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15509
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15510
					tce.tcpConnRemAddress =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15511
					    tcp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15512
					tce.tcpConnLocalAddress =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15513
					    tcp->tcp_ip_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15514
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15515
				tce.tcpConnLocalPort = ntohs(tcp->tcp_lport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15516
				tce.tcpConnRemPort = ntohs(tcp->tcp_fport);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15517
				/* Don't want just anybody seeing these... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15518
				if (ispriv) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15519
					tce.tcpConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15520
					    tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15521
					tce.tcpConnEntryInfo.ce_suna =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15522
					    tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15523
					tce.tcpConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15524
					    tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15525
					tce.tcpConnEntryInfo.ce_rack =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15526
					    tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15527
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15528
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15529
					 * Netstat, unfortunately, uses this to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15530
					 * get send/receive queue sizes.  How
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15531
					 * to fix?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15532
					 * Why not compute the difference only?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15533
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15534
					tce.tcpConnEntryInfo.ce_snxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15535
					    tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15536
					tce.tcpConnEntryInfo.ce_suna = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15537
					tce.tcpConnEntryInfo.ce_rnxt =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15538
					    tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15539
					tce.tcpConnEntryInfo.ce_rack = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15540
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15541
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15542
				tce.tcpConnEntryInfo.ce_swnd = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15543
				tce.tcpConnEntryInfo.ce_rwnd = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15544
				tce.tcpConnEntryInfo.ce_rto =  tcp->tcp_rto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15545
				tce.tcpConnEntryInfo.ce_mss =  tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15546
				tce.tcpConnEntryInfo.ce_state =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15547
				    tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15548
				(void) snmp_append_data2(mp_conn_data,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15549
				    &mp_conn_tail, (char *)&tce, sizeof (tce));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15550
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15551
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15552
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15554
	/* fixed length structure for IPv4 and IPv6 counters */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15555
	SET_MIB(tcp_mib.tcpConnTableSize, sizeof (mib2_tcpConnEntry_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15556
	SET_MIB(tcp_mib.tcp6ConnTableSize, sizeof (mib2_tcp6ConnEntry_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15557
	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15558
	optp->level = MIB2_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15559
	optp->name = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15560
	(void) snmp_append_data(mpdata, (char *)&tcp_mib, sizeof (tcp_mib));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15561
	optp->len = msgdsize(mpdata);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15562
	qreply(q, mpctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15564
	/* table of connections... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15565
	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15566
	    sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15567
	optp->level = MIB2_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15568
	optp->name = MIB2_TCP_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15569
	optp->len = msgdsize(mp_conn_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15570
	qreply(q, mp_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15572
	/* table of IPv6 connections... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15573
	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15574
	    sizeof (struct T_optmgmt_ack)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15575
	optp->level = MIB2_TCP6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15576
	optp->name = MIB2_TCP6_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15577
	optp->len = msgdsize(mp6_conn_data);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15578
	qreply(q, mp6_conn_ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15579
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15580
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15582
/* Return 0 if invalid set request, 1 otherwise, including non-tcp requests  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15583
/* ARGSUSED */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15584
int
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15585
tcp_snmp_set(queue_t *q, int level, int name, uchar_t *ptr, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15586
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15587
	mib2_tcpConnEntry_t	*tce = (mib2_tcpConnEntry_t *)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15589
	switch (level) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15590
	case MIB2_TCP:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15591
		switch (name) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15592
		case 13:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15593
			if (tce->tcpConnState != MIB2_TCP_deleteTCB)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15594
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15595
			/* TODO: delete entry defined by tce */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15596
			return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15597
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15598
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15599
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15600
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15601
		return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15602
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15603
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15605
/* Translate TCP state to MIB2 TCP state. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15606
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15607
tcp_snmp_state(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15608
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15609
	if (tcp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15610
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15611
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15612
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15613
	case TCPS_CLOSED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15614
	case TCPS_IDLE:	/* RFC1213 doesn't have analogue for IDLE & BOUND */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15615
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15616
		return (MIB2_TCP_closed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15617
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15618
		return (MIB2_TCP_listen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15619
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15620
		return (MIB2_TCP_synSent);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15621
	case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15622
		return (MIB2_TCP_synReceived);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15623
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15624
		return (MIB2_TCP_established);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15625
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15626
		return (MIB2_TCP_closeWait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15627
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15628
		return (MIB2_TCP_finWait1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15629
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15630
		return (MIB2_TCP_closing);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15631
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15632
		return (MIB2_TCP_lastAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15633
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15634
		return (MIB2_TCP_finWait2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15635
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15636
		return (MIB2_TCP_timeWait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15637
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15638
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15639
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15640
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15641
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15642
static char tcp_report_header[] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15643
	"TCP     " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15644
	"zone dest            snxt     suna     "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15645
	"swnd       rnxt     rack     rwnd       rto   mss   w sw rw t "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15646
	"recent   [lport,fport] state";
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15648
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15649
 * TCP status report triggered via the Named Dispatch mechanism.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15650
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15651
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15652
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15653
tcp_report_item(mblk_t *mp, tcp_t *tcp, int hashval, tcp_t *thisstream,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15654
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15655
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15656
	char hash[10], addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15657
	boolean_t ispriv = secpolicy_net_config(cr, B_TRUE) == 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15658
	char cflag;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15659
	in6_addr_t	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15660
	char buf[80];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15661
	uint_t print_len, buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15663
	buf_len = mp->b_datap->db_lim - mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15664
	if (buf_len <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15665
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15667
	if (hashval >= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15668
		(void) sprintf(hash, "%03d ", hashval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15669
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15670
		hash[0] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15672
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15673
	 * Note that we use the remote address in the tcp_b  structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15674
	 * This means that it will print out the real destination address,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15675
	 * not the next hop's address if source routing is used.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15676
	 * avoid the confusion on the output because user may not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15677
	 * know that source routing is used for a connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15678
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15679
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15680
		IN6_IPADDR_TO_V4MAPPED(tcp->tcp_remote, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15681
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15682
		v6dst = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15683
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15684
	(void) inet_ntop(AF_INET6, &v6dst, addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15685
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15686
	 * the ispriv checks are so that normal users cannot determine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15687
	 * sequence number information using NDD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15688
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15690
	if (TCP_IS_DETACHED(tcp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15691
		cflag = '*';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15692
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15693
		cflag = ' ';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15694
	print_len = snprintf((char *)mp->b_wptr, buf_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15695
	    "%s " MI_COL_PTRFMT_STR "%d %s %08x %08x %010d %08x %08x "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15696
	    "%010d %05ld %05d %1d %02d %02d %1d %08x %s%c\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15697
	    hash,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15698
	    (void *)tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15699
	    tcp->tcp_connp->conn_zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15700
	    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15701
	    (ispriv) ? tcp->tcp_snxt : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15702
	    (ispriv) ? tcp->tcp_suna : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15703
	    tcp->tcp_swnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15704
	    (ispriv) ? tcp->tcp_rnxt : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15705
	    (ispriv) ? tcp->tcp_rack : 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15706
	    tcp->tcp_rwnd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15707
	    tcp->tcp_rto,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15708
	    tcp->tcp_mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15709
	    tcp->tcp_snd_ws_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15710
	    tcp->tcp_snd_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15711
	    tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15712
	    tcp->tcp_snd_ts_ok,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15713
	    tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15714
	    tcp_display(tcp, buf, DISP_PORT_ONLY), cflag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15715
	if (print_len < buf_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15716
		((mblk_t *)mp)->b_wptr += print_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15717
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15718
		((mblk_t *)mp)->b_wptr += buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15719
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15720
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15722
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15723
 * TCP status report (for listeners only) triggered via the Named Dispatch
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15724
 * mechanism.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15725
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15726
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15727
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15728
tcp_report_listener(mblk_t *mp, tcp_t *tcp, int hashval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15729
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15730
	char addrbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15731
	in6_addr_t	v6dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15732
	uint_t print_len, buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15734
	buf_len = mp->b_datap->db_lim - mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15735
	if (buf_len <= 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15736
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15738
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15739
		IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src, &v6dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15740
		(void) inet_ntop(AF_INET6, &v6dst, addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15741
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15742
		(void) inet_ntop(AF_INET6, &tcp->tcp_ip6h->ip6_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15743
		    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15744
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15745
	print_len = snprintf((char *)mp->b_wptr, buf_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15746
	    "%03d "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15747
	    MI_COL_PTRFMT_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15748
	    "%d %s %05u %08u %d/%d/%d%c\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15749
	    hashval, (void *)tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15750
	    tcp->tcp_connp->conn_zoneid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15751
	    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15752
	    (uint_t)BE16_TO_U16(tcp->tcp_tcph->th_lport),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15753
	    tcp->tcp_conn_req_seqnum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15754
	    tcp->tcp_conn_req_cnt_q0, tcp->tcp_conn_req_cnt_q,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15755
	    tcp->tcp_conn_req_max,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15756
	    tcp->tcp_syn_defense ? '*' : ' ');
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15757
	if (print_len < buf_len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15758
		((mblk_t *)mp)->b_wptr += print_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15759
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15760
		((mblk_t *)mp)->b_wptr += buf_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15761
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15762
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15763
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15764
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15765
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15766
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15767
tcp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15768
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15769
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15770
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15771
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15772
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15773
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15775
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15776
	 * Because of the ndd constraint, at most we can have 64K buffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15777
	 * to put in all TCP info.  So to be more efficient, just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15778
	 * allocate a 64K buffer here, assuming we need that large buffer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15779
	 * This may be a problem as any user can read tcp_status.  Therefore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15780
	 * we limit the rate of doing this using tcp_ndd_get_info_interval.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15781
	 * This should be OK as normal users should not do this too often.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15782
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15783
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15784
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15785
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15786
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15787
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15788
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15789
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15790
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15791
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15792
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15793
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15794
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15795
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15796
	(void) mi_mpprintf(mp, "%s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15798
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15799
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15801
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15803
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15804
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15805
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15806
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15807
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15808
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15809
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15810
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15811
			tcp_report_item(mp->b_cont, tcp, -1, tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15812
			    cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15813
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15815
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15817
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15818
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15819
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15821
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15822
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15823
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15824
tcp_bind_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15825
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15826
	tf_t	*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15827
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15828
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15829
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15830
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15831
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15832
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15833
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15834
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15835
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15836
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15837
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15838
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15839
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15840
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15841
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15842
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15843
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15845
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15846
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15847
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15849
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15850
		tbf = &tcp_bind_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15851
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15852
		for (tcp = tbf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15853
		    tcp = tcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15854
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15855
			    zoneid != tcp->tcp_connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15856
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15857
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15858
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15859
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15860
			CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15861
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15862
		mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15863
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15864
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15865
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15866
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15868
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15869
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15870
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15871
tcp_listen_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15872
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15873
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15874
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15875
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15876
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15877
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15878
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15879
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15880
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15881
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15882
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15883
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15884
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15885
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15886
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15887
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15888
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15889
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15890
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15891
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15893
	(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15894
	    "    TCP    " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15895
	    "zone IP addr         port  seqnum   backlog (q0/q/max)");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15897
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15899
	for (i = 0; i < ipcl_bind_fanout_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15900
		connfp =  &ipcl_bind_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15901
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15902
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15903
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15904
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15905
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15906
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15907
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15908
			tcp_report_listener(mp->b_cont, tcp, i);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15909
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15910
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15912
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15913
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15914
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15915
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15916
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15917
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15918
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15919
tcp_conn_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15920
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15921
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15922
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15923
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15924
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15925
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15927
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15928
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15929
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15930
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15931
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15932
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15933
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15934
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15935
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15936
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15937
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15938
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15939
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15940
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15941
	(void) mi_mpprintf(mp, "tcp_conn_hash_size = %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15942
	    ipcl_conn_fanout_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15943
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15945
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15946
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15947
	for (i = 0; i < ipcl_conn_fanout_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15948
		connfp =  &ipcl_conn_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15949
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15950
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 15951
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15952
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15953
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15954
			    zoneid != connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15955
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15956
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15957
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15958
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15959
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15960
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15961
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15962
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15963
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15965
/* TCP status report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15966
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15967
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15968
tcp_acceptor_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15969
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15970
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15971
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15972
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15973
	zoneid_t zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15974
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15975
	/* Refer to comments in tcp_status_report(). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15976
	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15977
		if (ddi_get_lbolt() - tcp_last_ndd_get_info_time <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15978
		    drv_usectohz(tcp_ndd_get_info_interval * 1000)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15979
			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15980
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15981
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15982
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15983
	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15984
		/* The following may work even if we cannot get a large buf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15985
		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15986
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15987
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15988
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15989
	(void) mi_mpprintf(mp, "    %s", tcp_report_header);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15991
	zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15992
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15993
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15994
		tf = &tcp_acceptor_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15995
		mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15996
		for (tcp = tf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15997
		    tcp = tcp->tcp_acceptor_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15998
			if (zoneid != GLOBAL_ZONEID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 15999
			    zoneid != tcp->tcp_connp->conn_zoneid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16000
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16001
			tcp_report_item(mp->b_cont, tcp, i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16002
			    Q_TO_TCP(q), cr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16003
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16004
		mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16005
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16006
	tcp_last_ndd_get_info_time = ddi_get_lbolt();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16007
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16008
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16009
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16010
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16011
 * tcp_timer is the timer service routine.  It handles the retransmission,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16012
 * FIN_WAIT_2 flush, and zero window probe timeout events.  It figures out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16013
 * from the state of the tcp instance what kind of action needs to be done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16014
 * at the time it is called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16015
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16016
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16017
tcp_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16018
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16019
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16020
	clock_t		first_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16021
	clock_t		second_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16022
	clock_t		ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16023
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16024
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16025
	tcp_t		*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16026
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16027
	tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16028
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16029
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16030
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16031
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16032
	first_threshold =  tcp->tcp_first_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16033
	second_threshold = tcp->tcp_second_timer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16034
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16035
	case TCPS_IDLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16036
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16037
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16038
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16039
	case TCPS_SYN_RCVD: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16040
		tcp_t	*listener = tcp->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16041
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16042
		if (tcp->tcp_syn_rcvd_timeout == 0 && (listener != NULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16043
			ASSERT(tcp->tcp_rq == listener->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16044
			/* it's our first timeout */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16045
			tcp->tcp_syn_rcvd_timeout = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16046
			mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16047
			listener->tcp_syn_rcvd_timeout++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16048
			if (!listener->tcp_syn_defense &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16049
			    (listener->tcp_syn_rcvd_timeout >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16050
			    (tcp_conn_req_max_q0 >> 2)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16051
			    (tcp_conn_req_max_q0 > 200)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16052
				/* We may be under attack. Put on a defense. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16053
				listener->tcp_syn_defense = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16054
				cmn_err(CE_WARN, "High TCP connect timeout "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16055
				    "rate! System (port %d) may be under a "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16056
				    "SYN flood attack!",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16057
				    BE16_TO_U16(listener->tcp_tcph->th_lport));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16059
				listener->tcp_ip_addr_cache = kmem_zalloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16060
				    IP_ADDR_CACHE_SIZE * sizeof (ipaddr_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16061
				    KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16062
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16063
			mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16064
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16065
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16066
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16067
	case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16068
		first_threshold =  tcp->tcp_first_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16069
		second_threshold = tcp->tcp_second_ctimer_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16070
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16071
	case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16072
	case TCPS_FIN_WAIT_1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16073
	case TCPS_CLOSING:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16074
	case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16075
	case TCPS_LAST_ACK:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16076
		/* If we have data to rexmit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16077
		if (tcp->tcp_suna != tcp->tcp_snxt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16078
			clock_t	time_to_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16080
			BUMP_MIB(&tcp_mib, tcpTimRetrans);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16081
			if (!tcp->tcp_xmit_head)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16082
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16083
			time_to_wait = lbolt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16084
			    (clock_t)tcp->tcp_xmit_head->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16085
			time_to_wait = tcp->tcp_rto -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16086
			    TICK_TO_MSEC(time_to_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16087
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16088
			 * If the timer fires too early, 1 clock tick earlier,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16089
			 * restart the timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16090
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16091
			if (time_to_wait > msec_per_tick) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16092
				TCP_STAT(tcp_timer_fire_early);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16093
				TCP_TIMER_RESTART(tcp, time_to_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16094
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16095
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16096
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16097
			 * When we probe zero windows, we force the swnd open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16098
			 * If our peer acks with a closed window swnd will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16099
			 * set to zero by tcp_rput(). As long as we are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16100
			 * receiving acks tcp_rput will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16101
			 * reset 'tcp_ms_we_have_waited' so as not to trip the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16102
			 * first and second interval actions.  NOTE: the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16103
			 * interval is allowed to continue its exponential
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16104
			 * backoff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16105
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16106
			if (tcp->tcp_swnd == 0 || tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16107
				if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16108
					(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16109
					    SL_TRACE, "tcp_timer: zero win");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16110
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16111
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16112
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16113
				 * After retransmission, we need to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16114
				 * slow start.  Set the ssthresh to one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16115
				 * half of current effective window and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16116
				 * cwnd to one MSS.  Also reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16117
				 * tcp_cwnd_cnt.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16118
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16119
				 * Note that if tcp_ssthresh is reduced because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16120
				 * of ECN, do not reduce it again unless it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16121
				 * already one window of data away (tcp_cwr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16122
				 * should then be cleared) or this is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16123
				 * timeout for a retransmitted segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16124
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16125
				uint32_t npkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16126
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16127
				if (!tcp->tcp_cwr || tcp->tcp_rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16128
					npkt = ((tcp->tcp_timer_backoff ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16129
					    tcp->tcp_cwnd_ssthresh :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16130
					    tcp->tcp_snxt -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16131
					    tcp->tcp_suna) >> 1) / tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16132
					tcp->tcp_cwnd_ssthresh = MAX(npkt, 2) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16133
					    tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16134
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16135
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16136
				tcp->tcp_cwnd_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16137
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16138
					tcp->tcp_cwr = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16139
					tcp->tcp_cwr_snd_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16140
					tcp->tcp_ecn_cwr_sent = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16141
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16142
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16143
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16144
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16145
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16146
		 * We have something to send yet we cannot send.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16147
		 * reason can be:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16148
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16149
		 * 1. Zero send window: we need to do zero window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16150
		 * 2. Zero cwnd: because of ECN, we need to "clock out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16151
		 * segments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16152
		 * 3. SWS avoidance: receiver may have shrunk window,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16153
		 * reset our knowledge.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16154
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16155
		 * Note that condition 2 can happen with either 1 or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16156
		 * 3.  But 1 and 3 are exclusive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16157
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16158
		if (tcp->tcp_unsent != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16159
			if (tcp->tcp_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16160
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16161
				 * Set tcp_cwnd to 1 MSS so that a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16162
				 * new segment can be sent out.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16163
				 * are "clocking out" new data when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16164
				 * the network is really congested.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16165
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16166
				ASSERT(tcp->tcp_ecn_ok);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16167
				tcp->tcp_cwnd = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16168
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16169
			if (tcp->tcp_swnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16170
				/* Extend window for zero window probe */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16171
				tcp->tcp_swnd++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16172
				tcp->tcp_zero_win_probe = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16173
				BUMP_MIB(&tcp_mib, tcpOutWinProbe);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16174
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16175
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16176
				 * Handle timeout from sender SWS avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16177
				 * Reset our knowledge of the max send window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16178
				 * since the receiver might have reduced its
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16179
				 * receive buffer.  Avoid setting tcp_max_swnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16180
				 * to one since that will essentially disable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16181
				 * the SWS checks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16182
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16183
				 * Note that since we don't have a SWS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16184
				 * state variable, if the timeout is set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16185
				 * for ECN but not for SWS, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16186
				 * code will also be executed.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16187
				 * fine as tcp_max_swnd is updated
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16188
				 * constantly and it will not affect
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16189
				 * anything.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16190
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16191
				tcp->tcp_max_swnd = MAX(tcp->tcp_swnd, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16192
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16193
			tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16194
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16195
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16196
		/* Is there a FIN that needs to be to re retransmitted? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16197
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16198
		    !tcp->tcp_fin_acked)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16199
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16200
		/* Nothing to do, return without restarting timer. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16201
		TCP_STAT(tcp_timer_fire_miss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16202
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16203
	case TCPS_FIN_WAIT_2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16204
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16205
		 * User closed the TCP endpoint and peer ACK'ed our FIN.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16206
		 * We waited some time for for peer's FIN, but it hasn't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16207
		 * arrived.  We flush the connection now to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16208
		 * case where the peer has rebooted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16209
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16210
		if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16211
			(void) tcp_clean_death(tcp, 0, 23);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16212
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16213
			TCP_TIMER_RESTART(tcp, tcp_fin_wait_2_flush_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16214
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16215
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16216
	case TCPS_TIME_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16217
		(void) tcp_clean_death(tcp, 0, 24);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16218
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16219
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16220
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16221
			(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE|SL_ERROR,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16222
			    "tcp_timer: strange state (%d) %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16223
			    tcp->tcp_state, tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16224
			    DISP_PORT_ONLY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16225
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16226
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16227
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16228
	if ((ms = tcp->tcp_ms_we_have_waited) > second_threshold) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16229
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16230
		 * For zero window probe, we need to send indefinitely,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16231
		 * unless we have not heard from the other side for some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16232
		 * time...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16233
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16234
		if ((tcp->tcp_zero_win_probe == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16235
		    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16236
		    second_threshold)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16237
			BUMP_MIB(&tcp_mib, tcpTimRetransDrop);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16238
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16239
			 * If TCP is in SYN_RCVD state, send back a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16240
			 * RST|ACK as BSD does.  Note that tcp_zero_win_probe
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16241
			 * should be zero in TCPS_SYN_RCVD state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16242
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16243
			if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16244
				tcp_xmit_ctl("tcp_timer: RST sent on timeout "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16245
				    "in SYN_RCVD",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16246
				    tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16247
				    tcp->tcp_rnxt, TH_RST | TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16248
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16249
			(void) tcp_clean_death(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16250
			    tcp->tcp_client_errno ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16251
			    tcp->tcp_client_errno : ETIMEDOUT, 25);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16252
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16253
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16254
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16255
			 * Set tcp_ms_we_have_waited to second_threshold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16256
			 * so that in next timeout, we will do the above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16257
			 * check (lbolt - tcp_last_recv_time).  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16258
			 * also to avoid overflow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16259
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16260
			 * We don't need to decrement tcp_timer_backoff
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16261
			 * to avoid overflow because it will be decremented
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16262
			 * later if new timeout value is greater than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16263
			 * tcp_rexmit_interval_max.  In the case when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16264
			 * tcp_rexmit_interval_max is greater than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16265
			 * second_threshold, it means that we will wait
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16266
			 * longer than second_threshold to send the next
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16267
			 * window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16268
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16269
			tcp->tcp_ms_we_have_waited = second_threshold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16270
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16271
	} else if (ms > first_threshold) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16272
		if (tcp->tcp_snd_zcopy_aware && (!tcp->tcp_xmit_zc_clean) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16273
		    tcp->tcp_xmit_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16274
			tcp->tcp_xmit_head =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16275
			    tcp_zcopy_backoff(tcp, tcp->tcp_xmit_head, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16276
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16277
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16278
		 * We have been retransmitting for too long...  The RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16279
		 * we calculated is probably incorrect.  Reinitialize it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16280
		 * Need to compensate for 0 tcp_rtt_sa.  Reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16281
		 * tcp_rtt_update so that we won't accidentally cache a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16282
		 * bad value.  But only do this if this is not a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16283
		 * window probe.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16284
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16285
		if (tcp->tcp_rtt_sa != 0 && tcp->tcp_zero_win_probe == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16286
			tcp->tcp_rtt_sd += (tcp->tcp_rtt_sa >> 3) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16287
			    (tcp->tcp_rtt_sa >> 5);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16288
			tcp->tcp_rtt_sa = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16289
			tcp_ip_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16290
			tcp->tcp_rtt_update = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16291
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16292
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16293
	tcp->tcp_timer_backoff++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16294
	if ((ms = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16295
	    tcp_rexmit_interval_extra + (tcp->tcp_rtt_sa >> 5)) <
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16296
	    tcp_rexmit_interval_min) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16297
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16298
		 * This means the original RTO is tcp_rexmit_interval_min.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16299
		 * So we will use tcp_rexmit_interval_min as the RTO value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16300
		 * and do the backoff.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16301
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16302
		ms = tcp_rexmit_interval_min << tcp->tcp_timer_backoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16303
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16304
		ms <<= tcp->tcp_timer_backoff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16305
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16306
	if (ms > tcp_rexmit_interval_max) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16307
		ms = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16308
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16309
		 * ms is at max, decrement tcp_timer_backoff to avoid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16310
		 * overflow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16311
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16312
		tcp->tcp_timer_backoff--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16313
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16314
	tcp->tcp_ms_we_have_waited += ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16315
	if (tcp->tcp_zero_win_probe == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16316
		tcp->tcp_rto = ms;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16317
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16318
	TCP_TIMER_RESTART(tcp, ms);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16319
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16320
	 * This is after a timeout and tcp_rto is backed off.  Set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16321
	 * tcp_set_timer to 1 so that next time RTO is updated, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16322
	 * restart the timer with a correct value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16323
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16324
	tcp->tcp_set_timer = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16325
	mss = tcp->tcp_snxt - tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16326
	if (mss > tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16327
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16328
	if (mss > tcp->tcp_swnd && tcp->tcp_swnd != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16329
		mss = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16330
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16331
	if ((mp = tcp->tcp_xmit_head) != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16332
		mp->b_prev = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16333
	mp = tcp_xmit_mp(tcp, mp, mss, NULL, NULL, tcp->tcp_suna, B_TRUE, &mss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16334
	    B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16335
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16336
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16337
	 * When slow start after retransmission begins, start with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16338
	 * this seq no.  tcp_rexmit_max marks the end of special slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16339
	 * start phase.  tcp_snd_burst controls how many segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16340
	 * can be sent because of an ack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16341
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16342
	tcp->tcp_rexmit_nxt = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16343
	tcp->tcp_snd_burst = TCP_CWND_SS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16344
	if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16345
	    (tcp->tcp_unsent == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16346
		tcp->tcp_rexmit_max = tcp->tcp_fss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16347
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16348
		tcp->tcp_rexmit_max = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16349
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16350
	tcp->tcp_rexmit = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16351
	tcp->tcp_dupack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16353
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16354
	 * Remove all rexmit SACK blk to start from fresh.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16355
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16356
	if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16357
		TCP_NOTSACK_REMOVE_ALL(tcp->tcp_notsack_list);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16358
		tcp->tcp_num_notsack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16359
		tcp->tcp_cnt_notsack_list = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16360
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16361
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16362
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16364
	/* Attach credentials to retransmitted initial SYNs. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16365
	if (tcp->tcp_state == TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16366
		mblk_setcred(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16367
		DB_CPID(mp) = tcp->tcp_cpid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16368
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16370
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16371
	BUMP_MIB(&tcp_mib, tcpRetransSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16372
	UPDATE_MIB(&tcp_mib, tcpRetransBytes, mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16373
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16374
	tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16375
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16376
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16378
/* tcp_unbind is called by tcp_wput_proto to handle T_UNBIND_REQ messages. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16379
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16380
tcp_unbind(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16381
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16382
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16384
	switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16385
	case TCPS_BOUND:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16386
	case TCPS_LISTEN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16387
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16388
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16389
		tcp_err_ack(tcp, mp, TOUTSTATE, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16390
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16391
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16392
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16393
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16394
	 * Need to clean up all the eagers since after the unbind, segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16395
	 * will no longer be delivered to this listener stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16396
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16397
	mutex_enter(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16398
	if (tcp->tcp_conn_req_cnt_q0 != 0 || tcp->tcp_conn_req_cnt_q != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16399
		tcp_eager_cleanup(tcp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16400
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16401
	mutex_exit(&tcp->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16403
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16404
		tcp->tcp_ipha->ipha_src = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16405
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16406
		V6_SET_ZERO(tcp->tcp_ip6h->ip6_src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16407
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16408
	V6_SET_ZERO(tcp->tcp_ip_src_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16409
	bzero(tcp->tcp_tcph->th_lport, sizeof (tcp->tcp_tcph->th_lport));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16410
	tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16411
	tcp->tcp_state = TCPS_IDLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16412
	tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16413
	/* Send M_FLUSH according to TPI */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16414
	(void) putnextctl1(tcp->tcp_rq, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16415
	connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16416
	connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16417
	ipcl_hash_remove(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16418
	bzero(&connp->conn_ports, sizeof (connp->conn_ports));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16419
	mp = mi_tpi_ok_ack_alloc(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16420
	putnext(tcp->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16421
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16422
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16423
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16424
 * Don't let port fall into the privileged range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16425
 * Since the extra privileged ports can be arbitrary we also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16426
 * ensure that we exclude those from consideration.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16427
 * tcp_g_epriv_ports is not sorted thus we loop over it until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16428
 * there are no changes.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16429
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16430
 * Note: No locks are held when inspecting tcp_g_*epriv_ports
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16431
 * but instead the code relies on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16432
 * - the fact that the address of the array and its size never changes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16433
 * - the atomic assignment of the elements of the array
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16434
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16435
static in_port_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16436
tcp_update_next_port(in_port_t port, boolean_t random)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16437
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16438
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16440
	if (random && tcp_random_anon_port != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16441
		(void) random_get_pseudo_bytes((uint8_t *)&port,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16442
		    sizeof (in_port_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16443
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16444
		 * Unless changed by a sys admin, the smallest anon port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16445
		 * is 32768 and the largest anon port is 65535.  It is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16446
		 * very likely (50%) for the random port to be smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16447
		 * than the smallest anon port.  When that happens,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16448
		 * add port % (anon port range) to the smallest anon
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16449
		 * port to get the random port.  It should fall into the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16450
		 * valid anon port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16451
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16452
		if (port < tcp_smallest_anon_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16453
			port = tcp_smallest_anon_port +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16454
			    port % (tcp_largest_anon_port -
646
be34c04451cb 4461538 TCP connect does not pick local port well
gt145670
parents: 487
diff changeset
 16455
				tcp_smallest_anon_port);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16456
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16457
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16458
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16459
retry:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16460
	if (port < tcp_smallest_anon_port || port > tcp_largest_anon_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16461
		port = (in_port_t)tcp_smallest_anon_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16463
	if (port < tcp_smallest_nonpriv_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16464
		port = (in_port_t)tcp_smallest_nonpriv_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16466
	for (i = 0; i < tcp_g_num_epriv_ports; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16467
		if (port == tcp_g_epriv_ports[i]) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16468
			port++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16469
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16470
			 * Make sure whether the port is in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16471
			 * valid range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16472
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16473
			 * XXX Note that if tcp_g_epriv_ports contains
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16474
			 * all the anonymous ports this will be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16475
			 * infinite loop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16476
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16477
			goto retry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16478
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16479
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16480
	return (port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16481
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16482
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16483
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16484
 * Return the next anonymous port in the priviledged port range for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16485
 * bind checking.  It starts at IPPORT_RESERVED - 1 and goes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16486
 * downwards.  This is the same behavior as documented in the userland
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16487
 * library call rresvport(3N).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16488
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16489
static in_port_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16490
tcp_get_next_priv_port(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16491
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16492
	static in_port_t next_priv_port = IPPORT_RESERVED - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16494
	if (next_priv_port < tcp_min_anonpriv_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16495
		next_priv_port = IPPORT_RESERVED - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16496
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16497
	return (next_priv_port--);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16498
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16500
/* The write side r/w procedure. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16501
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16502
#if CCS_STATS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16503
struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16504
	struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16505
		int64_t count, bytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16506
	} tot, hit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16507
} wrw_stats;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16508
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16510
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16511
 * Call by tcp_wput() to handle all non data, except M_PROTO and M_PCPROTO,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16512
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16513
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16514
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16515
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16516
tcp_wput_nondata(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16517
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16518
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16519
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16520
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16521
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16522
	ASSERT(DB_TYPE(mp) != M_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16523
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16524
	 * TCP is D_MP and qprocsoff() is done towards the end of the tcp_close.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16525
	 * Once the close starts, streamhead and sockfs will not let any data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16526
	 * packets come down (close ensures that there are no threads using the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16527
	 * queue and no new threads will come down) but since qprocsoff()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16528
	 * hasn't happened yet, a M_FLUSH or some non data message might
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16529
	 * get reflected back (in response to our own FLUSHRW) and get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16530
	 * processed after tcp_close() is done. The conn would still be valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16531
	 * because a ref would have added but we need to check the state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16532
	 * before actually processing the packet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16533
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16534
	if (TCP_IS_DETACHED(tcp) || (tcp->tcp_state == TCPS_CLOSED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16535
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16536
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16537
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16538
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16539
	switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16540
	case M_IOCDATA:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16541
		tcp_wput_iocdata(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16542
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16543
	case M_FLUSH:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16544
		tcp_wput_flush(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16545
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16546
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16547
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16548
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16549
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16550
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16552
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16553
 * The TCP fast path write put procedure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16554
 * NOTE: the logic of the fast path is duplicated from tcp_wput_data()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16555
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16556
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16557
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16558
tcp_output(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16559
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16560
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16561
	int		hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16562
	int		plen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16563
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16564
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16565
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16566
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16567
	struct datab	*db;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16568
	uint32_t	suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16569
	uint32_t	mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16570
	ipaddr_t	*dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16571
	ipaddr_t	*src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16572
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16573
	int		usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16574
	conn_t		*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16575
	tcp_t		*tcp = connp->conn_tcp;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16576
	uint32_t	msize;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16578
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16579
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16580
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16581
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16582
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16583
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16584
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16585
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16586
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16587
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16588
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16590
	/* Bypass tcp protocol for fused tcp loopback */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16591
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16592
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16593
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16594
		tcp->tcp_squeue_bytes -= msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16595
		mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16596
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16597
		if (tcp_fuse_output(tcp, mp, msize))
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16598
			return;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16599
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16601
	mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16602
	if (tcp->tcp_xmit_zc_clean)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16603
		mp = tcp_zcopy_backoff(tcp, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16605
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16606
	len = (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16608
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16609
	 * Criteria for fast path:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16610
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16611
	 *   1. no unsent data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16612
	 *   2. single mblk in request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16613
	 *   3. connection established
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16614
	 *   4. data in mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16615
	 *   5. len <= mss
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16616
	 *   6. no tcp_valid bits
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16617
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16618
	if ((tcp->tcp_unsent != 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16619
	    (tcp->tcp_cork) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16620
	    (mp->b_cont != NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16621
	    (tcp->tcp_state != TCPS_ESTABLISHED) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16622
	    (len == 0) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16623
	    (len > mss) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16624
	    (tcp->tcp_valid_bits != 0)) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16625
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16626
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16627
		tcp->tcp_squeue_bytes -= msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16628
		mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16629
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16630
		tcp_wput_data(tcp, mp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16631
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16632
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16634
	ASSERT(tcp->tcp_xmit_tail_unsent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16635
	ASSERT(tcp->tcp_fin_sent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16636
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16637
	mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16638
	tcp->tcp_squeue_bytes -= len;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16639
	mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16640
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16641
	/* queue new packet onto retransmission queue */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16642
	if (tcp->tcp_xmit_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16643
		tcp->tcp_xmit_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16644
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16645
		tcp->tcp_xmit_last->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16646
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16647
	tcp->tcp_xmit_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16648
	tcp->tcp_xmit_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16649
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16650
	/* find out how much we can send */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16651
	/* BEGIN CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16652
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16653
	 *    un-acked           usable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16654
	 *  |--------------|-----------------|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16655
	 *  tcp_suna       tcp_snxt          tcp_suna+tcp_swnd
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16656
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16657
	/* END CSTYLED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16659
	/* start sending from tcp_snxt */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16660
	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16661
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16662
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16663
	 * Check to see if this connection has been idled for some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16664
	 * time and no ACK is expected.  If it is, we need to slow
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16665
	 * start again to get back the connection's "self-clock" as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16666
	 * described in VJ's paper.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16667
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16668
	 * Refer to the comment in tcp_mss_set() for the calculation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16669
	 * of tcp_cwnd after idle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16670
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16671
	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16672
	    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16673
		SET_TCP_INIT_CWND(tcp, mss, tcp_slow_start_after_idle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16674
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16676
	usable = tcp->tcp_swnd;		/* tcp window size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16677
	if (usable > tcp->tcp_cwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16678
		usable = tcp->tcp_cwnd;	/* congestion window smaller */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16679
	usable -= snxt;		/* subtract stuff already sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16680
	suna = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16681
	usable += suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16682
	/* usable can be < 0 if the congestion window is smaller */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16683
	if (len > usable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16684
		/* Can't send complete M_DATA in one shot */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16685
		goto slow;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16686
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16687
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16688
	if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16689
	    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16690
		tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16691
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16692
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16693
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16694
	 * determine if anything to send (Nagle).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16695
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16696
	 *   1. len < tcp_mss (i.e. small)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16697
	 *   2. unacknowledged data present
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16698
	 *   3. len < nagle limit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16699
	 *   4. last packet sent < nagle limit (previous packet sent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16700
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16701
	if ((len < mss) && (snxt != suna) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16702
	    (len < (int)tcp->tcp_naglim) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16703
	    (tcp->tcp_last_sent_len < tcp->tcp_naglim)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16704
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16705
		 * This was the first unsent packet and normally
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16706
		 * mss < xmit_hiwater so there is no need to worry
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16707
		 * about flow control. The next packet will go
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16708
		 * through the flow control check in tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16709
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16710
		/* leftover work from above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16711
		tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16712
		tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16714
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16715
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16716
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16717
	/* len <= tcp->tcp_mss && len == unsent so no silly window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16718
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16719
	if (snxt == suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16720
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16721
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16723
	/* we have always sent something */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16724
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16725
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16726
	tcp->tcp_snxt = snxt + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16727
	tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16729
	if ((mp1 = dupb(mp)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16730
		goto no_memory;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16731
	mp->b_prev = (mblk_t *)(uintptr_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16732
	mp->b_next = (mblk_t *)(uintptr_t)snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16734
	/* adjust tcp header information */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16735
	tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16736
	tcph->th_flags[0] = (TH_ACK|TH_PUSH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16738
	sum = len + tcp->tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16739
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16740
	U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16742
	U32_TO_ABE32(snxt, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16743
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16744
	BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16745
	UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16746
	BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16748
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16749
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16750
	    tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16752
	tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16754
	plen = len + tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16755
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16756
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16757
		tcp->tcp_ipha->ipha_length = htons(plen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16758
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16759
		tcp->tcp_ip6h->ip6_plen = htons(plen -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16760
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16761
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16762
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16763
	/* see if we need to allocate a mblk for the headers */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16764
	hdrlen = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16765
	rptr = mp1->b_rptr - hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16766
	db = mp1->b_datap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16767
	if ((db->db_ref != 2) || rptr < db->db_base ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16768
	    (!OK_32PTR(rptr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16769
		/* NOTE: we assume allocb returns an OK_32PTR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16770
		mp = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16771
		    tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16772
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16773
			freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16774
			goto no_memory;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16775
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16776
		mp->b_cont = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16777
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16778
		/* Leave room for Link Level header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16779
		/* hdrlen = tcp->tcp_hdr_len; */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16780
		rptr = &mp1->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16781
		mp1->b_wptr = &rptr[hdrlen];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16782
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16783
	mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16784
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16785
	/* Fill in the timestamp option. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16786
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16787
		U32_TO_BE32((uint32_t)lbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16788
		    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16789
		U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16790
		    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16791
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16792
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16793
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16795
	/* copy header into outgoing packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16796
	dst = (ipaddr_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16797
	src = (ipaddr_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16798
	dst[0] = src[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16799
	dst[1] = src[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16800
	dst[2] = src[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16801
	dst[3] = src[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16802
	dst[4] = src[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16803
	dst[5] = src[5];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16804
	dst[6] = src[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16805
	dst[7] = src[7];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16806
	dst[8] = src[8];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16807
	dst[9] = src[9];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16808
	if (hdrlen -= 40) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16809
		hdrlen >>= 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16810
		dst += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16811
		src += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16812
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16813
			*dst++ = *src++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16814
		} while (--hdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16815
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16817
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16818
	 * Set the ECN info in the TCP header.  Note that this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16819
	 * is not the template header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16820
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16821
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16822
		SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16824
		tcph = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16825
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16826
			tcph->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16827
		if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16828
			tcph->th_flags[0] |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16829
			tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16830
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16831
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16832
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16833
	if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16834
		ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16835
		*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16836
		tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16837
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16838
	TCP_RECORD_TRACE(tcp, mp1, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16839
	tcp_send_data(tcp, tcp->tcp_wq, mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16840
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16841
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16842
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16843
	 * If we ran out of memory, we pretend to have sent the packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16844
	 * and that it was lost on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16845
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16846
no_memory:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16847
	return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16849
slow:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16850
	/* leftover work from above */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16851
	tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16852
	tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16853
	tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16854
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16856
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16857
 * The function called through squeue to get behind eager's perimeter to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16858
 * finish the accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16859
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16860
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16861
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16862
tcp_accept_finish(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16863
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16864
	conn_t			*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16865
	tcp_t			*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16866
	queue_t			*q = tcp->tcp_rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16867
	mblk_t			*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16868
	mblk_t			*stropt_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16869
	struct  stroptions	*stropt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16870
	uint_t			thwin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16871
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16872
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16873
	 * Drop the eager's ref on the listener, that was placed when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16874
	 * this eager began life in tcp_conn_request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16875
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16876
	CONN_DEC_REF(tcp->tcp_saved_listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16877
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16878
	if (tcp->tcp_state <= TCPS_BOUND || tcp->tcp_accept_error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16879
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16880
		 * Someone blewoff the eager before we could finish
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16881
		 * the accept.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16882
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16883
		 * The only reason eager exists it because we put in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16884
		 * a ref on it when conn ind went up. We need to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16885
		 * a disconnect indication up while the last reference
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16886
		 * on the eager will be dropped by the squeue when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16887
		 * return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16888
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16889
		ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16890
		if (tcp->tcp_issocket || tcp->tcp_send_discon_ind) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16891
			struct	T_discon_ind	*tdi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16892
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16893
			(void) putnextctl1(q, M_FLUSH, FLUSHRW);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16894
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16895
			 * Let us reuse the incoming mblk to avoid memory
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16896
			 * allocation failure problems. We know that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16897
			 * size of the incoming mblk i.e. stroptions is greater
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16898
			 * than sizeof T_discon_ind. So the reallocb below
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16899
			 * can't fail.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16900
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16901
			freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16902
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16903
			ASSERT(DB_REF(mp) == 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16904
			mp = reallocb(mp, sizeof (struct T_discon_ind),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16905
			    B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16906
			ASSERT(mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16907
			DB_TYPE(mp) = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16908
			((union T_primitives *)mp->b_rptr)->type = T_DISCON_IND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16909
			tdi = (struct T_discon_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16910
			if (tcp->tcp_issocket) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16911
				tdi->DISCON_reason = ECONNREFUSED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16912
				tdi->SEQ_number = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16913
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16914
				tdi->DISCON_reason = ENOPROTOOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16915
				tdi->SEQ_number =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16916
				    tcp->tcp_conn_req_seqnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16917
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16918
			mp->b_wptr = mp->b_rptr + sizeof (struct T_discon_ind);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16919
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16920
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16921
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16922
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16923
		if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16924
			tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16925
			tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16926
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16927
		tcp->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16928
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16929
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16930
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16931
	mp1 = stropt_mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16932
	stropt_mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16933
	ASSERT(DB_TYPE(stropt_mp) == M_SETOPTS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16934
	stropt = (struct stroptions *)stropt_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16936
	while (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16937
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16938
		mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16939
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16940
		tcp->tcp_drop_opt_ack_cnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16941
		CALL_IP_WPUT(connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16942
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16943
	mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16945
	/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16946
	 * For a loopback connection with tcp_direct_sockfs on, note that
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16947
	 * we don't have to protect tcp_rcv_list yet because synchronous
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16948
	 * streams has not yet been enabled and tcp_fuse_rrw() cannot
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16949
	 * possibly race with us.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16950
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16951
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16952
	/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16953
	 * Set the max window size (tcp_rq->q_hiwat) of the acceptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16954
	 * properly.  This is the first time we know of the acceptor'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16955
	 * queue.  So we do it here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16956
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16957
	if (tcp->tcp_rcv_list == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16958
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16959
		 * Recv queue is empty, tcp_rwnd should not have changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16960
		 * That means it should be equal to the listener's tcp_rwnd.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16961
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16962
		tcp->tcp_rq->q_hiwat = tcp->tcp_rwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16963
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16964
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16965
		uint_t cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16966
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16967
		mp1 = tcp->tcp_rcv_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16968
		while ((mp = mp1) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16969
			mp1 = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16970
			cnt += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16971
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16972
		ASSERT(cnt != 0 && tcp->tcp_rcv_cnt == cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16973
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16974
		/* There is some data, add them back to get the max. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16975
		tcp->tcp_rq->q_hiwat = tcp->tcp_rwnd + tcp->tcp_rcv_cnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16976
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16977
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16978
	stropt->so_flags = SO_HIWAT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16979
	stropt->so_hiwat = MAX(q->q_hiwat, tcp_sth_rcv_hiwat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16981
	stropt->so_flags |= SO_MAXBLK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16982
	stropt->so_maxblk = tcp_maxpsz_set(tcp, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16983
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16984
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16985
	 * This is the first time we run on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16986
	 * queue after tcp_accept. So fix all the q parameters
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16987
	 * here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16988
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16989
	/* Allocate room for SACK options if needed. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16990
	stropt->so_flags |= SO_WROFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16991
	if (tcp->tcp_fused) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16992
		ASSERT(tcp->tcp_loopback);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 16993
		ASSERT(tcp->tcp_loopback_peer != NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16994
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16995
		 * For fused tcp loopback, set the stream head's write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16996
		 * offset value to zero since we won't be needing any room
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16997
		 * for TCP/IP headers.  This would also improve performance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16998
		 * since it would reduce the amount of work done by kmem.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 16999
		 * Non-fused tcp loopback case is handled separately below.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17000
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17001
		stropt->so_wroff = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17002
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17003
		 * Record the stream head's high water mark for this endpoint;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17004
		 * this is used for flow-control purposes in tcp_fuse_output().
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17005
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17006
		stropt->so_hiwat = tcp_fuse_set_rcv_hiwat(tcp, q->q_hiwat);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17007
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17008
		 * Update the peer's transmit parameters according to
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17009
		 * our recently calculated high water mark value.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17010
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17011
		(void) tcp_maxpsz_set(tcp->tcp_loopback_peer, B_TRUE);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17012
	} else if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17013
		stropt->so_wroff = tcp->tcp_hdr_len + TCPOPT_MAX_SACK_LEN +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17014
		    (tcp->tcp_loopback ? 0 : tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17015
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17016
		stropt->so_wroff = tcp->tcp_hdr_len + (tcp->tcp_loopback ? 0 :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17017
		    tcp_wroff_xtra);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17018
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17019
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17020
	/* Send the options up */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17021
	putnext(q, stropt_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17022
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17023
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17024
	 * Pass up any data and/or a fin that has been received.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17025
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17026
	 * Adjust receive window in case it had decreased
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17027
	 * (because there is data <=> tcp_rcv_list != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17028
	 * while the connection was detached. Note that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17029
	 * in case the eager was flow-controlled, w/o this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17030
	 * code, the rwnd may never open up again!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17031
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17032
	if (tcp->tcp_rcv_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17033
		/* We drain directly in case of fused tcp loopback */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17034
		if (!tcp->tcp_fused && canputnext(q)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17035
			tcp->tcp_rwnd = q->q_hiwat;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17036
			thwin = ((uint_t)BE16_TO_U16(tcp->tcp_tcph->th_win))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17037
			    << tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17038
			thwin -= tcp->tcp_rnxt - tcp->tcp_rack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17039
			if (tcp->tcp_state >= TCPS_ESTABLISHED &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17040
			    (q->q_hiwat - thwin >= tcp->tcp_mss)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17041
				tcp_xmit_ctl(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17042
				    tcp, (tcp->tcp_swnd == 0) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17043
				    tcp->tcp_suna : tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17044
				    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17045
				BUMP_MIB(&tcp_mib, tcpOutWinUpdate);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17046
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17048
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17049
		(void) tcp_rcv_drain(q, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17051
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17052
		 * For fused tcp loopback, back-enable peer endpoint
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17053
		 * if it's currently flow-controlled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17054
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17055
		if (tcp->tcp_fused &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17056
		    tcp->tcp_loopback_peer->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17057
			tcp_t *peer_tcp = tcp->tcp_loopback_peer;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17058
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17059
			ASSERT(peer_tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17060
			ASSERT(peer_tcp->tcp_fused);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17061
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17062
			tcp_clrqfull(peer_tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17063
			TCP_STAT(tcp_fusion_backenabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17064
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17065
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17066
	ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17067
	if (tcp->tcp_fin_rcvd && !tcp->tcp_ordrel_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17068
		mp = mi_tpi_ordrel_ind();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17069
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17070
			tcp->tcp_ordrel_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17071
			putnext(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17072
			if (tcp->tcp_deferred_clean_death) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17073
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17074
				 * tcp_clean_death was deferred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17075
				 * for T_ORDREL_IND - do it now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17076
				 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17077
				(void) tcp_clean_death(tcp,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17078
				    tcp->tcp_client_errno, 21);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17079
				tcp->tcp_deferred_clean_death = B_FALSE;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17080
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17081
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17082
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17083
			 * Run the orderly release in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17084
			 * service routine.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17085
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17086
			qenable(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17087
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17088
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17089
	if (tcp->tcp_hard_binding) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17090
		tcp->tcp_hard_binding = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17091
		tcp->tcp_hard_bound = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17092
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17093
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17094
	tcp->tcp_detached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17095
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17096
	/* We can enable synchronous streams now */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17097
	if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17098
		tcp_fuse_syncstr_enable_pair(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17099
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17100
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17101
	if (tcp->tcp_ka_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17102
		tcp->tcp_ka_last_intrvl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17103
		tcp->tcp_ka_tid = TCP_TIMER(tcp, tcp_keepalive_killer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17104
		    MSEC_TO_TICK(tcp->tcp_ka_interval));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17105
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17107
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17108
	 * At this point, eager is fully established and will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17109
	 * have the following references -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17110
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17111
	 * 2 references for connection to exist (1 for TCP and 1 for IP).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17112
	 * 1 reference for the squeue which will be dropped by the squeue as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17113
	 *	soon as this function returns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17114
	 * There will be 1 additonal reference for being in classifier
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17115
	 *	hash list provided something bad hasn't happened.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17116
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17117
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17118
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17119
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17121
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17122
 * The function called through squeue to get behind listener's perimeter to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17123
 * send a deffered conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17124
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17125
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17126
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17127
tcp_send_pending(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17128
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17129
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17130
	tcp_t *listener = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17132
	if (listener->tcp_state == TCPS_CLOSED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17133
	    TCP_IS_DETACHED(listener)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17134
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17135
		 * If listener has closed, it would have caused a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17136
		 * a cleanup/blowoff to happen for the eager.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17137
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17138
		tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17139
		struct T_conn_ind	*conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17140
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17141
		conn_ind = (struct T_conn_ind *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17142
		bcopy(mp->b_rptr + conn_ind->OPT_offset, &tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17143
		    conn_ind->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17144
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17145
		 * We need to drop the ref on eager that was put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17146
		 * tcp_rput_data() before trying to send the conn_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17147
		 * to listener. The conn_ind was deferred in tcp_send_conn_ind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17148
		 * and tcp_wput_accept() is sending this deferred conn_ind but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17149
		 * listener is closed so we drop the ref.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17150
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17151
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17152
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17153
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17154
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17155
	putnext(listener->tcp_rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17156
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17157
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17159
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17160
 * This is the STREAMS entry point for T_CONN_RES coming down on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17161
 * Acceptor STREAM when  sockfs listener does accept processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17162
 * Read the block comment on top pf tcp_conn_request().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17163
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17164
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17165
tcp_wput_accept(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17166
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17167
	queue_t *rq = RD(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17168
	struct T_conn_res *conn_res;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17169
	tcp_t *eager;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17170
	tcp_t *listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17171
	struct T_ok_ack *ok;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17172
	t_scalar_t PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17173
	mblk_t *opt_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17174
	conn_t *econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17175
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17176
	ASSERT(DB_TYPE(mp) == M_PROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17178
	conn_res = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17179
	ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17180
	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_res)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17181
		mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17182
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17183
			putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17184
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17185
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17186
	switch (conn_res->PRIM_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17187
	case O_T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17188
	case T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17189
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17190
		 * We pass up an err ack if allocb fails. This will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17191
		 * cause sockfs to issue a T_DISCON_REQ which will cause
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17192
		 * tcp_eager_blowoff to be called. sockfs will then call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17193
		 * rq->q_qinfo->qi_qclose to cleanup the acceptor stream.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17194
		 * we need to do the allocb up here because we have to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17195
		 * make sure rq->q_qinfo->qi_qclose still points to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17196
		 * correct function (tcpclose_accept) in case allocb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17197
		 * fails.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17198
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17199
		opt_mp = allocb(sizeof (struct stroptions), BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17200
		if (opt_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17201
			mp = mi_tpi_err_ack_alloc(mp, TPROTO, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17202
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17203
				putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17204
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17205
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17207
		bcopy(mp->b_rptr + conn_res->OPT_offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17208
		    &eager, conn_res->OPT_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17209
		PRIM_type = conn_res->PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17210
		mp->b_datap->db_type = M_PCPROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17211
		mp->b_wptr = mp->b_rptr + sizeof (struct T_ok_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17212
		ok = (struct T_ok_ack *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17213
		ok->PRIM_type = T_OK_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17214
		ok->CORRECT_prim = PRIM_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17215
		econnp = eager->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17216
		econnp->conn_dev = (dev_t)q->q_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17217
		eager->tcp_rq = rq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17218
		eager->tcp_wq = q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17219
		rq->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17220
		rq->q_qinfo = &tcp_rinit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17221
		q->q_ptr = econnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17222
		q->q_qinfo = &tcp_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17223
		listener = eager->tcp_listener;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17224
		eager->tcp_issocket = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17225
		eager->tcp_cred = econnp->conn_cred =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17226
		    listener->tcp_connp->conn_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17227
		crhold(econnp->conn_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17228
		econnp->conn_zoneid = listener->tcp_connp->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17229
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17230
		/* Put the ref for IP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17231
		CONN_INC_REF(econnp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17233
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17234
		 * We should have minimum of 3 references on the conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17235
		 * at this point. One each for TCP and IP and one for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17236
		 * the T_conn_ind that was sent up when the 3-way handshake
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17237
		 * completed. In the normal case we would also have another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17238
		 * reference (making a total of 4) for the conn being in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17239
		 * classifier hash list. However the eager could have received
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17240
		 * an RST subsequently and tcp_closei_local could have removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17241
		 * the eager from the classifier hash list, hence we can't
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17242
		 * assert that reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17243
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17244
		ASSERT(econnp->conn_ref >= 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17245
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17246
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17247
		 * Send the new local address also up to sockfs. There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17248
		 * should already be enough space in the mp that came
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17249
		 * down from soaccept().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17250
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17251
		if (eager->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17252
			sin_t *sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17254
			ASSERT((mp->b_datap->db_lim - mp->b_datap->db_base) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17255
			    (sizeof (struct T_ok_ack) + sizeof (sin_t)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17256
			sin = (sin_t *)mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17257
			mp->b_wptr += sizeof (sin_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17258
			sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17259
			sin->sin_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17260
			sin->sin_addr.s_addr = eager->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17261
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17262
			sin6_t *sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17264
			ASSERT((mp->b_datap->db_lim - mp->b_datap->db_base) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17265
			    sizeof (struct T_ok_ack) + sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17266
			sin6 = (sin6_t *)mp->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17267
			mp->b_wptr += sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17268
			sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17269
			sin6->sin6_port = eager->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17270
			if (eager->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17271
				sin6->sin6_flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17272
				IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17273
					eager->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17274
					    &sin6->sin6_addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17275
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17276
				ASSERT(eager->tcp_ip6h != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17277
				sin6->sin6_flowinfo =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17278
				    eager->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17279
				    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17280
				sin6->sin6_addr = eager->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17281
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17282
			sin6->sin6_scope_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17283
			sin6->__sin6_src_id = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17284
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17286
		putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17288
		opt_mp->b_datap->db_type = M_SETOPTS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17289
		opt_mp->b_wptr += sizeof (struct stroptions);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17291
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17292
		 * Prepare for inheriting IPV6_BOUND_IF and IPV6_RECVPKTINFO
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17293
		 * from listener to acceptor. The message is chained on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17294
		 * bind_mp which tcp_rput_other will send down to IP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17295
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17296
		if (listener->tcp_bound_if != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17297
			/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17298
			mp = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17299
			    IPV6_BOUND_IF, (char *)&listener->tcp_bound_if,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17300
			    sizeof (int));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17301
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17302
				linkb(opt_mp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17303
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17304
		if (listener->tcp_ipv6_recvancillary & TCP_IPV6_RECVPKTINFO) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17305
			uint_t on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17306
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17307
			/* allocate optmgmt req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17308
			mp = tcp_setsockopt_mp(IPPROTO_IPV6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17309
			    IPV6_RECVPKTINFO, (char *)&on, sizeof (on));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17310
			if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17311
				linkb(opt_mp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17312
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17313
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17314
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17315
		mutex_enter(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17316
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17317
		if (listener->tcp_eager_prev_q0->tcp_conn_def_q0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17319
			tcp_t *tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17320
			tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17321
			mblk_t *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17322
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17323
			tcp = listener->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17324
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17325
			 * listener->tcp_eager_prev_q0 points to the TAIL of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17326
			 * deferred T_conn_ind queue. We need to get to the head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17327
			 * of the queue in order to send up T_conn_ind the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17328
			 * order as how the 3WHS is completed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17329
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17330
			while (tcp != listener) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17331
				if (!tcp->tcp_eager_prev_q0->tcp_conn_def_q0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17332
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17333
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17334
					tcp = tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17335
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17336
			ASSERT(tcp != listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17337
			mp1 = tcp->tcp_conn.tcp_eager_conn_ind;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17338
			tcp->tcp_conn.tcp_eager_conn_ind = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17339
			/* Move from q0 to q */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17340
			ASSERT(listener->tcp_conn_req_cnt_q0 > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17341
			listener->tcp_conn_req_cnt_q0--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17342
			listener->tcp_conn_req_cnt_q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17343
			tcp->tcp_eager_next_q0->tcp_eager_prev_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17344
			    tcp->tcp_eager_prev_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17345
			tcp->tcp_eager_prev_q0->tcp_eager_next_q0 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17346
			    tcp->tcp_eager_next_q0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17347
			tcp->tcp_eager_prev_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17348
			tcp->tcp_eager_next_q0 = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17349
			tcp->tcp_conn_def_q0 = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17351
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17352
			 * Insert at end of the queue because sockfs sends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17353
			 * down T_CONN_RES in chronological order. Leaving
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17354
			 * the older conn indications at front of the queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17355
			 * helps reducing search time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17356
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17357
			tail = listener->tcp_eager_last_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17358
			if (tail != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17359
				tail->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17360
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17361
				listener->tcp_eager_next_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17362
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17363
			listener->tcp_eager_last_q = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17364
			tcp->tcp_eager_next_q = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17365
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17366
			/* Need to get inside the listener perimeter */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17367
			CONN_INC_REF(listener->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17368
			squeue_fill(listener->tcp_connp->conn_sqp, mp1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17369
			    tcp_send_pending, listener->tcp_connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17370
			    SQTAG_TCP_SEND_PENDING);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17371
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17372
		tcp_eager_unlink(eager);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17373
		mutex_exit(&listener->tcp_eager_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17375
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17376
		 * At this point, the eager is detached from the listener
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17377
		 * but we still have an extra refs on eager (apart from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17378
		 * usual tcp references). The ref was placed in tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17379
		 * before sending the conn_ind in tcp_send_conn_ind.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17380
		 * The ref will be dropped in tcp_accept_finish().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17381
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17382
		squeue_enter_nodrain(econnp->conn_sqp, opt_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17383
		    tcp_accept_finish, econnp, SQTAG_TCP_ACCEPT_FINISH_Q0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17384
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17385
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17386
		mp = mi_tpi_err_ack_alloc(mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17387
		if (mp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17388
			putnext(rq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17389
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17390
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17391
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17392
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17393
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17394
tcp_wput(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17395
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17396
	conn_t	*connp = Q_TO_CONN(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17397
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17398
	void (*output_proc)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17399
	t_scalar_t type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17400
	uchar_t *rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17401
	struct iocblk	*iocp;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17402
	uint32_t	msize;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17404
	ASSERT(connp->conn_ref >= 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17405
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17406
	switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17407
	case M_DATA:
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17408
		tcp = connp->conn_tcp;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17409
		ASSERT(tcp != NULL);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17410
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17411
		msize = msgdsize(mp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17412
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17413
		mutex_enter(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17414
		CONN_INC_REF_LOCKED(connp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17415
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17416
		tcp->tcp_squeue_bytes += msize;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17417
		if (TCP_UNSENT_BYTES(tcp) > tcp->tcp_xmit_hiwater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17418
			mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17419
			tcp_setqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17420
		} else
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17421
			mutex_exit(&connp->conn_lock);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17422
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17423
		(*tcp_squeue_wput_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17424
		    tcp_output, connp, SQTAG_TCP_OUTPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17425
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17426
	case M_PROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17427
	case M_PCPROTO:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17428
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17429
		 * if it is a snmp message, don't get behind the squeue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17430
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17431
		tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17432
		rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17433
		if ((mp->b_wptr - rptr) >= sizeof (t_scalar_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17434
			type = ((union T_primitives *)rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17435
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17436
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17437
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17438
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17439
				    "tcp_wput_proto, dropping one...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17440
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17441
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17442
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17443
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17444
		if (type == T_SVR4_OPTMGMT_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17445
			cred_t	*cr = DB_CREDDEF(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17446
			    tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17447
			if (snmpcom_req(q, mp, tcp_snmp_set, tcp_snmp_get,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17448
			    cr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17449
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17450
				 * This was a SNMP request
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17451
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17452
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17453
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17454
				output_proc = tcp_wput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17455
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17456
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17457
			output_proc = tcp_wput_proto;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17458
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17459
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17460
	case M_IOCTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17461
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17462
		 * Most ioctls can be processed right away without going via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17463
		 * squeues - process them right here. Those that do require
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17464
		 * squeue (currently TCP_IOC_DEFAULT_Q and _SIOCSOCKFALLBACK)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17465
		 * are processed by tcp_wput_ioctl().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17466
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17467
		iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17468
		tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17469
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17470
		switch (iocp->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17471
		case TCP_IOC_ABORT_CONN:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17472
			tcp_ioctl_abort_conn(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17473
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17474
		case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17475
			if (tcp->tcp_state < TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17476
				iocp->ioc_error = ENOTCONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17477
				iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17478
				mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17479
				qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17480
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17481
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17482
			/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17483
		case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17484
			mi_copyin(q, mp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17485
			    SIZEOF_STRUCT(strbuf, iocp->ioc_flag));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17486
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17487
		case ND_SET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17488
			/* nd_getset does the necessary checks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17489
		case ND_GET:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17490
			if (!nd_getset(q, tcp_g_nd, mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17491
				CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17492
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17493
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17494
			qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17495
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17496
		case TCP_IOC_DEFAULT_Q:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17497
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17498
			 * Wants to be the default wq. Check the credentials
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17499
			 * first, the rest is executed via squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17500
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17501
			if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17502
				iocp->ioc_error = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17503
				iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17504
				mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17505
				qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17506
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17507
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17508
			output_proc = tcp_wput_ioctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17509
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17510
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17511
			output_proc = tcp_wput_ioctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17512
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17513
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17514
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17515
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17516
		output_proc = tcp_wput_nondata;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17517
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17518
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17520
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17521
	(*tcp_squeue_wput_proc)(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17522
	    output_proc, connp, SQTAG_TCP_WPUT_OTHER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17523
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17524
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17525
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17526
 * Initial STREAMS write side put() procedure for sockets. It tries to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17527
 * handle the T_CAPABILITY_REQ which sockfs sends down while setting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17528
 * up the socket without using the squeue. Non T_CAPABILITY_REQ messages
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17529
 * are handled by tcp_wput() as usual.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17530
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17531
 * All further messages will also be handled by tcp_wput() because we cannot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17532
 * be sure that the above short cut is safe later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17533
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17534
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17535
tcp_wput_sock(queue_t *wq, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17536
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17537
	conn_t			*connp = Q_TO_CONN(wq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17538
	tcp_t			*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17539
	struct T_capability_req	*car = (struct T_capability_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17540
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17541
	ASSERT(wq->q_qinfo == &tcp_sock_winit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17542
	wq->q_qinfo = &tcp_winit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17543
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17544
	ASSERT(IPCL_IS_TCP(connp));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17545
	ASSERT(TCP_IS_SOCKET(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17546
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17547
	if (DB_TYPE(mp) == M_PCPROTO &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17548
	    MBLKL(mp) == sizeof (struct T_capability_req) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17549
	    car->PRIM_type == T_CAPABILITY_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17550
		tcp_capability_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17551
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17552
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17554
	tcp_wput(wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17555
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17557
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17558
tcp_zcopy_check(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17559
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17560
	conn_t	*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17561
	ire_t	*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17562
	boolean_t	zc_enabled = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17564
	if (do_tcpzcopy == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17565
		zc_enabled = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17566
	else if (tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17567
	    IPCL_IS_CONNECTED(connp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17568
	    (connp->conn_flags & IPCL_CHECK_POLICY) == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17569
	    connp->conn_dontroute == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17570
	    connp->conn_xmit_if_ill == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17571
	    connp->conn_nofailover_ill == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17572
	    do_tcpzcopy == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17573
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17574
		 * the checks above  closely resemble the fast path checks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17575
		 * in tcp_send_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17576
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17577
		mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17578
		ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17579
		ASSERT(!(connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17580
		if (ire != NULL && !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17581
			IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17582
			if (ire->ire_stq != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17583
				ill_t	*ill = (ill_t *)ire->ire_stq->q_ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17585
				zc_enabled = ill && (ill->ill_capabilities &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17586
				    ILL_CAPAB_ZEROCOPY) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17587
				    (ill->ill_zerocopy_capab->
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17588
				    ill_zerocopy_flags != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17589
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17590
			IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17591
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17592
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17594
	tcp->tcp_snd_zcopy_on = zc_enabled;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17595
	if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17596
		if (zc_enabled) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17597
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17598
			TCP_STAT(tcp_zcopy_on);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17599
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17600
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMUNSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17601
			TCP_STAT(tcp_zcopy_off);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17602
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17603
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17604
	return (zc_enabled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17605
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17606
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17607
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17608
tcp_zcopy_disable(tcp_t *tcp, mblk_t *bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17609
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17610
	if (do_tcpzcopy == 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17611
		return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17612
	else if (tcp->tcp_snd_zcopy_on) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17613
		tcp->tcp_snd_zcopy_on = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17614
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17615
			(void) mi_set_sth_copyopt(tcp->tcp_rq, ZCVMUNSAFE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17616
			TCP_STAT(tcp_zcopy_disable);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17617
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17618
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17619
	return (tcp_zcopy_backoff(tcp, bp, 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17620
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17621
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17622
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17623
 * Backoff from a zero-copy mblk by copying data to a new mblk and freeing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17624
 * the original desballoca'ed segmapped mblk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17625
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17626
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17627
tcp_zcopy_backoff(tcp_t *tcp, mblk_t *bp, int fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17628
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17629
	mblk_t *head, *tail, *nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17630
	if (IS_VMLOANED_MBLK(bp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17631
		TCP_STAT(tcp_zcopy_backoff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17632
		if ((head = copyb(bp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17633
			/* fail to backoff; leave it for the next backoff */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17634
			tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17635
			return (bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17636
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17637
		if (bp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17638
			if (fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17639
				tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17640
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17641
				head->b_datap->db_struioflag |= STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17642
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17643
		nbp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17644
		if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17645
			head->b_prev = bp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17646
			head->b_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17647
			if (tcp->tcp_xmit_tail == bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17648
				tcp->tcp_xmit_tail = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17649
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17650
		bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17651
		bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17652
		freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17653
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17654
		head = bp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17655
		nbp = bp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17656
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17657
	tail = head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17658
	while (nbp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17659
		if (IS_VMLOANED_MBLK(nbp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17660
			TCP_STAT(tcp_zcopy_backoff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17661
			if ((tail->b_cont = copyb(nbp)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17662
				tcp->tcp_xmit_zc_clean = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17663
				tail->b_cont = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17664
				return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17665
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17666
			tail = tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17667
			if (nbp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17668
				if (fix_xmitlist)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17669
					tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17670
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17671
					tail->b_datap->db_struioflag |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17672
					    STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17673
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17674
			bp = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17675
			nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17676
			if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17677
				tail->b_prev = bp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17678
				tail->b_next = bp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17679
				if (tcp->tcp_xmit_tail == bp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17680
					tcp->tcp_xmit_tail = tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17681
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17682
			bp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17683
			bp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17684
			freeb(bp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17685
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17686
			tail->b_cont = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17687
			tail = nbp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17688
			nbp = nbp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17689
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17690
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17691
	if (fix_xmitlist) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17692
		tcp->tcp_xmit_last = tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17693
		tcp->tcp_xmit_zc_clean = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17694
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17695
	return (head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17696
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17698
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17699
tcp_zcopy_notify(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17700
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17701
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17702
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17703
	if (tcp->tcp_detached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17704
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17705
	stp = STREAM(tcp->tcp_rq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17706
	mutex_enter(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17707
	stp->sd_flag |= STZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17708
	cv_broadcast(&stp->sd_zcopy_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17709
	mutex_exit(&stp->sd_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17710
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17712
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17713
tcp_send_data(tcp_t *tcp, queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17714
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17715
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17716
	ipaddr_t	src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17717
	ipaddr_t	dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17718
	uint32_t	cksum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17719
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17720
	uint16_t	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17721
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17722
	conn_t		*connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17723
	uint32_t	hcksum_txflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17724
	mblk_t		*ire_fp_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17725
	uint_t		ire_fp_mp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17726
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17727
	ASSERT(DB_TYPE(mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17729
	ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17730
	src = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17731
	dst = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17733
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17734
	 * Drop off slow path for IPv6 and also if options are present.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17735
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17736
	if (tcp->tcp_ipversion != IPV4_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17737
	    !IPCL_IS_CONNECTED(connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17738
	    (connp->conn_flags & IPCL_CHECK_POLICY) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17739
	    connp->conn_dontroute ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17740
	    connp->conn_xmit_if_ill != NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17741
	    connp->conn_nofailover_ill != NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17742
	    ipha->ipha_ident == IP_HDR_INCLUDED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17743
	    ipha->ipha_version_and_hdr_length != IP_SIMPLE_HDR_VERSION ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17744
	    IPP_ENABLED(IPP_LOCAL_OUT)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17745
		if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17746
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17747
		TCP_STAT(tcp_ip_send);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17748
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17749
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17750
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17752
	mutex_enter(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17753
	ire = connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17754
	ASSERT(!(connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17755
	if (ire != NULL && ire->ire_addr == dst &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17756
	    !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17757
		IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17758
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17759
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17760
		boolean_t cached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17762
		/* force a recheck later on */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17763
		tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17764
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17765
		TCP_DBGSTAT(tcp_ire_null1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17766
		connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17767
		mutex_exit(&connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17768
		if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17769
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17770
		ire = ire_cache_lookup(dst, connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17771
		if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17772
			if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17773
				mp = tcp_zcopy_backoff(tcp, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17774
			TCP_STAT(tcp_ire_null);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17775
			CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17776
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17777
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17778
		IRE_REFHOLD_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17779
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17780
		 * Since we are inside the squeue, there cannot be another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17781
		 * thread in TCP trying to set the conn_ire_cache now.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17782
		 * check for IRE_MARK_CONDEMNED ensures that an interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17783
		 * unplumb thread has not yet started cleaning up the conns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17784
		 * Hence we don't need to grab the conn lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17785
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17786
		if (!(connp->conn_state_flags & CONN_CLOSING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17787
			rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17788
			if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17789
				connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17790
				cached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17791
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17792
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17793
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17795
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17796
		 * We can continue to use the ire but since it was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17797
		 * not cached, we should drop the extra reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17798
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17799
		if (!cached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17800
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17801
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17803
	if (ire->ire_flags & RTF_MULTIRT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17804
	    ire->ire_stq == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17805
	    ire->ire_max_frag < ntohs(ipha->ipha_length) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17806
	    (ire_fp_mp = ire->ire_fp_mp) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17807
	    (ire_fp_mp_len = MBLKL(ire_fp_mp)) > MBLKHEAD(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17808
		if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17809
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17810
		TCP_STAT(tcp_ip_ire_send);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17811
		IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17812
		CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17813
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17815
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17816
	ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17817
	if (connp->conn_outgoing_ill != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17818
		ill_t *conn_outgoing_ill = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17819
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17820
		 * Choose a good ill in the group to send the packets on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17821
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17822
		ire = conn_set_outgoing_ill(connp, ire, &conn_outgoing_ill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17823
		ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17824
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17825
	ASSERT(ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17827
	if (!tcp->tcp_ire_ill_check_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17828
		tcp_ire_ill_check(tcp, ire, ill, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17829
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17830
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17831
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17832
	ASSERT(ipha->ipha_ident == 0 || ipha->ipha_ident == IP_HDR_INCLUDED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17833
	ipha->ipha_ident = (uint16_t)atomic_add_32_nv(&ire->ire_ident, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17834
#ifndef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17835
	ipha->ipha_ident = (ipha->ipha_ident << 8) | (ipha->ipha_ident >> 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17836
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17838
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17839
	 * Check to see if we need to re-enable MDT for this connection
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17840
	 * because it was previously disabled due to changes in the ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17841
	 * note that by doing it here, this re-enabling only applies when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17842
	 * the packet is not dispatched through CALL_IP_WPUT().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17843
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17844
	 * That means for IPv4, it is worth re-enabling MDT for the fastpath
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17845
	 * case, since that's how we ended up here.  For IPv6, we do the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17846
	 * re-enabling work in ip_xmit_v6(), albeit indirectly via squeue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17847
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17848
	if (connp->conn_mdt_ok && !tcp->tcp_mdt && ILL_MDT_USABLE(ill)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17849
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17850
		 * Restore MDT for this connection, so that next time around
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17851
		 * it is eligible to go through tcp_multisend() path again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17852
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17853
		TCP_STAT(tcp_mdt_conn_resumed1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17854
		tcp->tcp_mdt = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17855
		ip1dbg(("tcp_send_data: reenabling MDT for connp %p on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17856
		    "interface %s\n", (void *)connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17857
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17858
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17859
	if (tcp->tcp_snd_zcopy_aware) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17860
		if ((ill->ill_capabilities & ILL_CAPAB_ZEROCOPY) == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17861
		    (ill->ill_zerocopy_capab->ill_zerocopy_flags == 0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17862
			mp = tcp_zcopy_disable(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17863
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17864
		 * we shouldn't need to reset ipha as the mp containing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17865
		 * ipha should never be a zero-copy mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17866
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17867
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17868
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17869
	if (ILL_HCKSUM_CAPABLE(ill) && dohwcksum) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17870
		ASSERT(ill->ill_hcksum_capab != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17871
		hcksum_txflags = ill->ill_hcksum_capab->ill_hcksum_txflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17872
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17874
	/* pseudo-header checksum (do it in parts for IP header checksum) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17875
	cksum = (dst >> 16) + (dst & 0xFFFF) + (src >> 16) + (src & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17876
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17877
	ASSERT(ipha->ipha_version_and_hdr_length == IP_SIMPLE_HDR_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17878
	up = IPH_TCPH_CHECKSUMP(ipha, IP_SIMPLE_HDR_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17879
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17880
	IP_CKSUM_XMIT_FAST(ire->ire_ipversion, hcksum_txflags, mp, ipha, up,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17881
	    IPPROTO_TCP, IP_SIMPLE_HDR_LENGTH, ntohs(ipha->ipha_length), cksum);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17882
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17883
	/* Software checksum? */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17884
	if (DB_CKSUMFLAGS(mp) == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17885
		TCP_STAT(tcp_out_sw_cksum);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17886
		TCP_STAT_UPDATE(tcp_out_sw_cksum_bytes,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17887
		    ntohs(ipha->ipha_length) - IP_SIMPLE_HDR_LENGTH);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17888
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17889
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17890
	ipha->ipha_fragment_offset_and_flags |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17891
	    (uint32_t)htons(ire->ire_frag_flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17892
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17893
	/* Calculate IP header checksum if hardware isn't capable */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17894
	if (!(DB_CKSUMFLAGS(mp) & HCK_IPV4_HDRCKSUM)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17895
		IP_HDR_CKSUM(ipha, cksum, ((uint32_t *)ipha)[0],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17896
		    ((uint16_t *)ipha)[4]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17897
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17899
	ASSERT(DB_TYPE(ire_fp_mp) == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17900
	mp->b_rptr = (uchar_t *)ipha - ire_fp_mp_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17901
	bcopy(ire_fp_mp->b_rptr, mp->b_rptr, ire_fp_mp_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17903
	UPDATE_OB_PKT_COUNT(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17904
	ire->ire_last_used_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17905
	BUMP_MIB(&ip_mib, ipOutRequests);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17906
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17907
	if (ILL_POLL_CAPABLE(ill)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17908
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17909
		 * Send the packet directly to DLD, where it may be queued
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17910
		 * depending on the availability of transmit resources at
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17911
		 * the media layer.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17912
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 17913
		IP_POLL_ILL_TX(ill, mp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17914
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17915
		putnext(ire->ire_stq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17916
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17917
	IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17918
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17919
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17920
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17921
 * This handles the case when the receiver has shrunk its win. Per RFC 1122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17922
 * if the receiver shrinks the window, i.e. moves the right window to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17923
 * left, the we should not send new data, but should retransmit normally the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17924
 * old unacked data between suna and suna + swnd. We might has sent data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17925
 * that is now outside the new window, pretend that we didn't send  it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17926
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17927
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17928
tcp_process_shrunk_swnd(tcp_t *tcp, uint32_t shrunk_count)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17929
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17930
	uint32_t	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17931
	mblk_t		*xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17932
	int32_t		offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17933
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17934
	ASSERT(shrunk_count > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17935
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17936
	/* Pretend we didn't send the data outside the window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17937
	snxt -= shrunk_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17939
	/* Get the mblk and the offset in it per the shrunk window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17940
	xmit_tail = tcp_get_seg_mp(tcp, snxt, &offset);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17941
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17942
	ASSERT(xmit_tail != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17943
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17944
	/* Reset all the values per the now shrunk window */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17945
	tcp->tcp_snxt = snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17946
	tcp->tcp_xmit_tail = xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17947
	tcp->tcp_xmit_tail_unsent = xmit_tail->b_wptr - xmit_tail->b_rptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17948
	    offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17949
	tcp->tcp_unsent += shrunk_count;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17951
	if (tcp->tcp_suna == tcp->tcp_snxt && tcp->tcp_swnd == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17952
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17953
		 * Make sure the timer is running so that we will probe a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17954
		 * window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17955
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17956
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17957
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17958
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17960
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17961
 * The TCP normal data output path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17962
 * NOTE: the logic of the fast path is duplicated from this function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17963
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17964
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17965
tcp_wput_data(tcp_t *tcp, mblk_t *mp, boolean_t urgent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17966
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17967
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17968
	mblk_t		*local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17969
	mblk_t		*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17970
	uint32_t	snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17971
	int		tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17972
	int		tcpstate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17973
	int		usable = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17974
	mblk_t		*xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17975
	queue_t		*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17976
	int32_t		mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17977
	int32_t		num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17978
	int32_t		tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17979
	int32_t		tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17980
	int		mdt_thres;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17981
	int		rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17982
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17983
	tcpstate = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17984
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17985
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17986
		 * tcp_wput_data() with NULL mp should only be called when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17987
		 * there is unsent data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17988
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17989
		ASSERT(tcp->tcp_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17990
		/* Really tacky... but we need this for detached closes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17991
		len = tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17992
		goto data_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17993
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17994
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17995
#if CCS_STATS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17996
	wrw_stats.tot.count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17997
	wrw_stats.tot.bytes += msgdsize(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17998
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 17999
	ASSERT(mp->b_datap->db_type == M_DATA);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18000
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18001
	 * Don't allow data after T_ORDREL_REQ or T_DISCON_REQ,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18002
	 * or before a connection attempt has begun.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18003
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18004
	if (tcpstate < TCPS_SYN_SENT || tcpstate > TCPS_CLOSE_WAIT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18005
	    (tcp->tcp_valid_bits & TCP_FSS_VALID) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18006
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18007
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18008
			cmn_err(CE_WARN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18009
			    "tcp_wput_data: data after ordrel, %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18010
			    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18011
			    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18012
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18013
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18014
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18015
				    SL_TRACE|SL_ERROR,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18016
				    "tcp_wput_data: data after ordrel, %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18017
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18018
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18019
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18020
#endif /* DEBUG */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18021
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18022
		if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18023
		    (mp->b_datap->db_struioflag & STRUIO_ZCNOTIFY) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18024
			tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18025
		freemsg(mp);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18026
		if (tcp->tcp_flow_stopped &&
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18027
		    TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18028
			tcp_clrqfull(tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18029
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18030
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18031
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18032
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18033
	/* Strip empties */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18034
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18035
		ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18036
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18037
		len = (int)(mp->b_wptr - mp->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18038
		if (len > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18039
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18040
		mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18041
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18042
		freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18043
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18044
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18045
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18046
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18047
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18048
	/* If we are the first on the list ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18049
	if (tcp->tcp_xmit_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18050
		tcp->tcp_xmit_head = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18051
		tcp->tcp_xmit_tail = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18052
		tcp->tcp_xmit_tail_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18053
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18054
		/* If tiny tx and room in txq tail, pullup to save mblks. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18055
		struct datab *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18057
		mp1 = tcp->tcp_xmit_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18058
		if (len < tcp_tx_pull_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18059
		    (dp = mp1->b_datap)->db_ref == 1 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18060
		    dp->db_lim - mp1->b_wptr >= len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18061
			ASSERT(len > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18062
			ASSERT(!mp1->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18063
			if (len == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18064
				*mp1->b_wptr++ = *mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18065
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18066
				bcopy(mp->b_rptr, mp1->b_wptr, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18067
				mp1->b_wptr += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18068
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18069
			if (mp1 == tcp->tcp_xmit_tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18070
				tcp->tcp_xmit_tail_unsent += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18071
			mp1->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18072
			if (tcp->tcp_snd_zcopy_aware &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18073
			    (mp->b_datap->db_struioflag & STRUIO_ZCNOTIFY))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18074
				mp1->b_datap->db_struioflag |= STRUIO_ZCNOTIFY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18075
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18076
			mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18077
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18078
			tcp->tcp_xmit_last->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18079
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18080
		len += tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18081
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18082
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18083
	/* Tack on however many more positive length mblks we have */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18084
	if ((mp1 = mp->b_cont) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18085
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18086
			int tlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18087
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18088
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18089
			tlen = (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18090
			if (tlen <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18091
				mp->b_cont = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18092
				freeb(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18093
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18094
				len += tlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18095
				mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18096
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18097
		} while ((mp1 = mp->b_cont) != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18098
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18099
	tcp->tcp_xmit_last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18100
	tcp->tcp_unsent = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18102
	if (urgent)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18103
		usable = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18105
data_null:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18106
	snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18107
	xmit_tail = tcp->tcp_xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18108
	tail_unsent = tcp->tcp_xmit_tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18110
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18111
	 * Note that tcp_mss has been adjusted to take into account the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18112
	 * timestamp option if applicable.  Because SACK options do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18113
	 * appear in every TCP segments and they are of variable lengths,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18114
	 * they cannot be included in tcp_mss.  Thus we need to calculate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18115
	 * the actual segment length when we need to send a segment which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18116
	 * includes SACK options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18117
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18118
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18119
		int32_t	opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18121
		num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18122
		    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18123
		opt_len = num_sack_blk * sizeof (sack_blk_t) + TCPOPT_NOP_LEN *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18124
		    2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18125
		mss = tcp->tcp_mss - opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18126
		tcp_hdr_len = tcp->tcp_hdr_len + opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18127
		tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len + opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18128
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18129
		mss = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18130
		tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18131
		tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18132
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18133
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18134
	if ((tcp->tcp_suna == snxt) && !tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18135
	    (TICK_TO_MSEC(lbolt - tcp->tcp_last_recv_time) >= tcp->tcp_rto)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18136
		SET_TCP_INIT_CWND(tcp, mss, tcp_slow_start_after_idle);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18137
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18138
	if (tcpstate == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18139
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18140
		 * The three-way connection establishment handshake is not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18141
		 * complete yet. We want to queue the data for transmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18142
		 * after entering ESTABLISHED state (RFC793). A jump to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18143
		 * "done" label effectively leaves data on the queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18144
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18145
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18146
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18147
		int usable_r = tcp->tcp_swnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18148
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18149
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18150
		 * In the special case when cwnd is zero, which can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18151
		 * happen if the connection is ECN capable, return now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18152
		 * New segments is sent using tcp_timer().  The timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18153
		 * is set in tcp_rput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18154
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18155
		if (tcp->tcp_cwnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18156
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18157
			 * Note that tcp_cwnd is 0 before 3-way handshake is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18158
			 * finished.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18159
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18160
			ASSERT(tcp->tcp_ecn_ok ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18161
			    tcp->tcp_state < TCPS_ESTABLISHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18162
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18163
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18165
		/* NOTE: trouble if xmitting while SYN not acked? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18166
		usable_r -= snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18167
		usable_r += tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18169
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18170
		 * Check if the receiver has shrunk the window.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18171
		 * tcp_wput_data() with NULL mp is called, tcp_fin_sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18172
		 * cannot be set as there is unsent data, so FIN cannot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18173
		 * be sent out.  Otherwise, we need to take into account
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18174
		 * of FIN as it consumes an "invisible" sequence number.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18175
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18176
		ASSERT(tcp->tcp_fin_sent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18177
		if (usable_r < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18178
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18179
			 * The receiver has shrunk the window and we have sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18180
			 * -usable_r date beyond the window, re-adjust.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18181
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18182
			 * If TCP window scaling is enabled, there can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18183
			 * round down error as the advertised receive window
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18184
			 * is actually right shifted n bits.  This means that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18185
			 * the lower n bits info is wiped out.  It will look
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18186
			 * like the window is shrunk.  Do a check here to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18187
			 * see if the shrunk amount is actually within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18188
			 * error in window calculation.  If it is, just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18189
			 * return.  Note that this check is inside the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18190
			 * shrunk window check.  This makes sure that even
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18191
			 * though tcp_process_shrunk_swnd() is not called,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18192
			 * we will stop further processing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18193
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18194
			if ((-usable_r >> tcp->tcp_snd_ws) > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18195
				tcp_process_shrunk_swnd(tcp, -usable_r);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18196
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18197
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18198
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18200
		/* usable = MIN(swnd, cwnd) - unacked_bytes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18201
		if (tcp->tcp_swnd > tcp->tcp_cwnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18202
			usable_r -= tcp->tcp_swnd - tcp->tcp_cwnd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18203
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18204
		/* usable = MIN(usable, unsent) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18205
		if (usable_r > len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18206
			usable_r = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18208
		/* usable = MAX(usable, {1 for urgent, 0 for data}) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18209
		if (usable_r > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18210
			usable = usable_r;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18211
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18212
			/* Bypass all other unnecessary processing. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18213
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18214
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18215
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18217
	local_time = (mblk_t *)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18219
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18220
	 * "Our" Nagle Algorithm.  This is not the same as in the old
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18221
	 * BSD.  This is more in line with the true intent of Nagle.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18222
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18223
	 * The conditions are:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18224
	 * 1. The amount of unsent data (or amount of data which can be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18225
	 *    sent, whichever is smaller) is less than Nagle limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18226
	 * 2. The last sent size is also less than Nagle limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18227
	 * 3. There is unack'ed data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18228
	 * 4. Urgent pointer is not set.  Send urgent data ignoring the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18229
	 *    Nagle algorithm.  This reduces the probability that urgent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18230
	 *    bytes get "merged" together.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18231
	 * 5. The app has not closed the connection.  This eliminates the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18232
	 *    wait time of the receiving side waiting for the last piece of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18233
	 *    (small) data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18234
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18235
	 * If all are satisified, exit without sending anything.  Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18236
	 * that Nagle limit can be smaller than 1 MSS.  Nagle limit is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18237
	 * the smaller of 1 MSS and global tcp_naglim_def (default to be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18238
	 * 4095).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18239
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18240
	if (usable < (int)tcp->tcp_naglim &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18241
	    tcp->tcp_naglim > tcp->tcp_last_sent_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18242
	    snxt != tcp->tcp_suna &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18243
	    !(tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18244
	    !(tcp->tcp_valid_bits & TCP_FSS_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18245
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18246
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18248
	if (tcp->tcp_cork) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18249
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18250
		 * if the tcp->tcp_cork option is set, then we have to force
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18251
		 * TCP not to send partial segment (smaller than MSS bytes).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18252
		 * We are calculating the usable now based on full mss and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18253
		 * will save the rest of remaining data for later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18254
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18255
		if (usable < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18256
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18257
		usable = (usable / mss) * mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18258
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18259
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18260
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18261
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18262
	    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18263
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18264
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18265
	 * Determine if it's worthwhile to attempt MDT, based on:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18266
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18267
	 * 1. Simple TCP/IP{v4,v6} (no options).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18268
	 * 2. IPSEC/IPQoS processing is not needed for the TCP connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18269
	 * 3. If the TCP connection is in ESTABLISHED state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18270
	 * 4. The TCP is not detached.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18271
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18272
	 * If any of the above conditions have changed during the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18273
	 * connection, stop using MDT and restore the stream head
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18274
	 * parameters accordingly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18275
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18276
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18277
	    ((tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18278
	    tcp->tcp_ip_hdr_len != IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18279
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18280
	    tcp->tcp_ip_hdr_len != IPV6_HDR_LEN) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18281
	    tcp->tcp_state != TCPS_ESTABLISHED ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18282
	    TCP_IS_DETACHED(tcp) || !CONN_IS_MD_FASTPATH(tcp->tcp_connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18283
	    CONN_IPSEC_OUT_ENCAPSULATED(tcp->tcp_connp) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18284
	    IPP_ENABLED(IPP_LOCAL_OUT))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18285
		tcp->tcp_connp->conn_mdt_ok = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18286
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18287
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18288
		/* Anything other than detached is considered pathological */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18289
		if (!TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18290
			TCP_STAT(tcp_mdt_conn_halted1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18291
			(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18292
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18293
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18295
	/* Use MDT if sendable amount is greater than the threshold */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18296
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18297
	    (mdt_thres = mss << tcp_mdt_smss_threshold, usable > mdt_thres) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18298
	    (tail_unsent > mdt_thres || (xmit_tail->b_cont != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18299
	    MBLKL(xmit_tail->b_cont) > mdt_thres)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18300
	    (tcp->tcp_valid_bits == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18301
	    tcp->tcp_valid_bits == TCP_FSS_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18302
		ASSERT(tcp->tcp_connp->conn_mdt_ok);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18303
		rc = tcp_multisend(q, tcp, mss, tcp_hdr_len, tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18304
		    num_sack_blk, &usable, &snxt, &tail_unsent, &xmit_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18305
		    local_time, mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18306
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18307
		rc = tcp_send(q, tcp, mss, tcp_hdr_len, tcp_tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18308
		    num_sack_blk, &usable, &snxt, &tail_unsent, &xmit_tail,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18309
		    local_time, INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18310
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18311
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18312
	/* Pretend that all we were trying to send really got sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18313
	if (rc < 0 && tail_unsent < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18314
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18315
			xmit_tail = xmit_tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18316
			xmit_tail->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18317
			ASSERT((uintptr_t)(xmit_tail->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18318
			    xmit_tail->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18319
			tail_unsent += (int)(xmit_tail->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18320
			    xmit_tail->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18321
		} while (tail_unsent < 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18322
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18323
done:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18324
	tcp->tcp_xmit_tail = xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18325
	tcp->tcp_xmit_tail_unsent = tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18326
	len = tcp->tcp_snxt - snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18327
	if (len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18328
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18329
		 * If new data was sent, need to update the notsack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18330
		 * list, which is, afterall, data blocks that have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18331
		 * not been sack'ed by the receiver.  New data is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18332
		 * not sack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18333
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18334
		if (tcp->tcp_snd_sack_ok && tcp->tcp_notsack_list != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18335
			/* len is a negative value. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18336
			tcp->tcp_pipe -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18337
			tcp_notsack_update(&(tcp->tcp_notsack_list),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18338
			    tcp->tcp_snxt, snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18339
			    &(tcp->tcp_num_notsack_blk),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18340
			    &(tcp->tcp_cnt_notsack_list));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18341
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18342
		tcp->tcp_snxt = snxt + tcp->tcp_fin_sent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18343
		tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18344
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18345
		if ((snxt + len) == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18346
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18347
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18348
	} else if (snxt == tcp->tcp_suna && tcp->tcp_swnd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18349
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18350
		 * Didn't send anything. Make sure the timer is running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18351
		 * so that we will probe a zero window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18352
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18353
		TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18354
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18355
	/* Note that len is the amount we just sent but with a negative sign */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18356
	tcp->tcp_unsent += len;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18357
	if (tcp->tcp_flow_stopped) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18358
		if (TCP_UNSENT_BYTES(tcp) <= tcp->tcp_xmit_lowater) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18359
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18360
		}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18361
	} else if (TCP_UNSENT_BYTES(tcp) >= tcp->tcp_xmit_hiwater) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18362
		tcp_setqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18363
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18364
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18365
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18366
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18367
 * tcp_fill_header is called by tcp_send() and tcp_multisend() to fill the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18368
 * outgoing TCP header with the template header, as well as other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18369
 * options such as time-stamp, ECN and/or SACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18370
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18371
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18372
tcp_fill_header(tcp_t *tcp, uchar_t *rptr, clock_t now, int num_sack_blk)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18373
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18374
	tcph_t *tcp_tmpl, *tcp_h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18375
	uint32_t *dst, *src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18376
	int hdrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18377
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18378
	ASSERT(OK_32PTR(rptr));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18379
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18380
	/* Template header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18381
	tcp_tmpl = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18382
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18383
	/* Header of outgoing packet */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18384
	tcp_h = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18386
	/* dst and src are opaque 32-bit fields, used for copying */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18387
	dst = (uint32_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18388
	src = (uint32_t *)tcp->tcp_iphc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18389
	hdrlen = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18390
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18391
	/* Fill time-stamp option if needed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18392
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18393
		U32_TO_BE32((uint32_t)now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18394
		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18395
		U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18396
		    (char *)tcp_tmpl + TCP_MIN_HEADER_LENGTH + 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18397
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18398
		ASSERT(tcp->tcp_tcp_hdr_len == TCP_MIN_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18399
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18400
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18401
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18402
	 * Copy the template header; is this really more efficient than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18403
	 * calling bcopy()?  For simple IPv4/TCP, it may be the case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18404
	 * but perhaps not for other scenarios.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18405
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18406
	dst[0] = src[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18407
	dst[1] = src[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18408
	dst[2] = src[2];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18409
	dst[3] = src[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18410
	dst[4] = src[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18411
	dst[5] = src[5];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18412
	dst[6] = src[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18413
	dst[7] = src[7];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18414
	dst[8] = src[8];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18415
	dst[9] = src[9];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18416
	if (hdrlen -= 40) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18417
		hdrlen >>= 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18418
		dst += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18419
		src += 10;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18420
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18421
			*dst++ = *src++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18422
		} while (--hdrlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18423
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18425
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18426
	 * Set the ECN info in the TCP header if it is not a zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18427
	 * window probe.  Zero window probe is only sent in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18428
	 * tcp_wput_data() and tcp_timer().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18429
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18430
	if (tcp->tcp_ecn_ok && !tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18431
		SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18432
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18433
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18434
			tcp_h->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18435
		if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18436
			tcp_h->th_flags[0] |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18437
			tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18438
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18439
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18440
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18441
	/* Fill in SACK options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18442
	if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18443
		uchar_t *wptr = rptr + tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18444
		sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18445
		int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18446
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18447
		wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18448
		wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18449
		wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18450
		wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18451
		    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18452
		wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18454
		tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18455
		for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18456
			U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18457
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18458
			U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18459
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18460
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18461
		tcp_h->th_offset_and_rsrvd[0] +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18462
		    ((num_sack_blk * 2 + 1) << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18463
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18464
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18466
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18467
 * tcp_mdt_add_attrs() is called by tcp_multisend() in order to attach
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18468
 * the destination address and SAP attribute, and if necessary, the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18469
 * hardware checksum offload attribute to a Multidata message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18470
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18471
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18472
tcp_mdt_add_attrs(multidata_t *mmd, const mblk_t *dlmp, const boolean_t hwcksum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18473
    const uint32_t start, const uint32_t stuff, const uint32_t end,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18474
    const uint32_t flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18475
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18476
	/* Add global destination address & SAP attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18477
	if (dlmp == NULL || !ip_md_addr_attr(mmd, NULL, dlmp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18478
		ip1dbg(("tcp_mdt_add_attrs: can't add global physical "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18479
		    "destination address+SAP\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18481
		if (dlmp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18482
			TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18483
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18484
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18485
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18486
	/* Add global hwcksum attribute */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18487
	if (hwcksum &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18488
	    !ip_md_hcksum_attr(mmd, NULL, start, stuff, end, flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18489
		ip1dbg(("tcp_mdt_add_attrs: can't add global hardware "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18490
		    "checksum attribute\n"));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18491
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18492
		TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18493
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18494
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18496
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18497
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18498
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18499
/*
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18500
 * Smaller and private version of pdescinfo_t used specifically for TCP,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18501
 * which allows for only two payload spans per packet.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18502
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18503
typedef struct tcp_pdescinfo_s PDESCINFO_STRUCT(2) tcp_pdescinfo_t;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18504
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18505
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18506
 * tcp_multisend() is called by tcp_wput_data() for Multidata Transmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18507
 * scheme, and returns one the following:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18508
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18509
 * -1 = failed allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18510
 *  0 = success; burst count reached, or usable send window is too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18511
 *      and that we'd rather wait until later before sending again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18512
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18513
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18514
tcp_multisend(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18515
    const int tcp_tcp_hdr_len, const int num_sack_blk, int *usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18516
    uint_t *snxt, int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18517
    const int mdt_thres)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18518
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18519
	mblk_t		*md_mp_head, *md_mp, *md_pbuf, *md_pbuf_nxt, *md_hbuf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18520
	multidata_t	*mmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18521
	uint_t		obsegs, obbytes, hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18522
	uint_t		cur_hdr_off, cur_pld_off, base_pld_off, first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18523
	int		num_burst_seg, max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18524
	pdesc_t		*pkt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18525
	tcp_pdescinfo_t	tcp_pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18526
	pdescinfo_t	*pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18527
	int		pbuf_idx, pbuf_idx_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18528
	int		seg_len, len, spill, af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18529
	boolean_t	add_buffer, zcopy, clusterwide;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18530
	boolean_t	rconfirm = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18531
	boolean_t	done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18532
	uint32_t	cksum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18533
	uint32_t	hwcksum_flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18534
	ire_t		*ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18535
	ill_t		*ill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18536
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18537
	ip6_t		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18538
	ipaddr_t	src, dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18539
	ill_zerocopy_capab_t *zc_cap = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18540
	uint16_t	*up;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18541
	int		err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18543
#ifdef	_BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18544
#define	IPVER(ip6h)	((((uint32_t *)ip6h)[0] >> 28) & 0x7)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18545
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18546
#define	IPVER(ip6h)	((((uint32_t *)ip6h)[0] >> 4) & 0x7)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18547
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18548
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18549
#define	PREP_NEW_MULTIDATA() {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18550
	mmd = NULL;				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18551
	md_mp = md_hbuf = NULL;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18552
	cur_hdr_off = 0;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18553
	max_pld = tcp->tcp_mdt_max_pld;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18554
	pbuf_idx = pbuf_idx_nxt = -1;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18555
	add_buffer = B_TRUE;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18556
	zcopy = B_FALSE;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18557
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18559
#define	PREP_NEW_PBUF() {			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18560
	md_pbuf = md_pbuf_nxt = NULL;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18561
	pbuf_idx = pbuf_idx_nxt = -1;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18562
	cur_pld_off = 0;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18563
	first_snxt = *snxt;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18564
	ASSERT(*tail_unsent > 0);		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18565
	base_pld_off = MBLKL(*xmit_tail) - *tail_unsent; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18566
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18567
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18568
	ASSERT(mdt_thres >= mss);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18569
	ASSERT(*usable > 0 && *usable > mdt_thres);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18570
	ASSERT(tcp->tcp_state == TCPS_ESTABLISHED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18571
	ASSERT(!TCP_IS_DETACHED(tcp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18572
	ASSERT(tcp->tcp_valid_bits == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18573
	    tcp->tcp_valid_bits == TCP_FSS_VALID);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18574
	ASSERT((tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18575
	    tcp->tcp_ip_hdr_len == IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18576
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18577
	    tcp->tcp_ip_hdr_len == IPV6_HDR_LEN));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18578
	ASSERT(tcp->tcp_connp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18579
	ASSERT(CONN_IS_MD_FASTPATH(tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18580
	ASSERT(!CONN_IPSEC_OUT_ENCAPSULATED(tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18581
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18582
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18583
	 * Note that tcp will only declare at most 2 payload spans per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18584
	 * packet, which is much lower than the maximum allowable number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18585
	 * of packet spans per Multidata.  For this reason, we use the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18586
	 * privately declared and smaller descriptor info structure, in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18587
	 * order to save some stack space.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18588
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18589
	pkt_info = (pdescinfo_t *)&tcp_pkt_info;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18590
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18591
	af = (tcp->tcp_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18592
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18593
		dst = tcp->tcp_ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18594
		src = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18595
		ASSERT(!CLASSD(dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18596
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18597
	ASSERT(af == AF_INET ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18598
	    !IN6_IS_ADDR_MULTICAST(&tcp->tcp_ip6h->ip6_dst));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18600
	obsegs = obbytes = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18601
	num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18602
	md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18603
	PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18605
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18606
	 * Before we go on further, make sure there is an IRE that we can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18607
	 * use, and that the ILL supports MDT.  Otherwise, there's no point
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18608
	 * in proceeding any further, and we should just hand everything
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18609
	 * off to the legacy path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18610
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18611
	mutex_enter(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18612
	ire = tcp->tcp_connp->conn_ire_cache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18613
	ASSERT(!(tcp->tcp_connp->conn_state_flags & CONN_INCIPIENT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18614
	if (ire != NULL && ((af == AF_INET && ire->ire_addr == dst) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18615
	    (af == AF_INET6 && IN6_ARE_ADDR_EQUAL(&ire->ire_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18616
	    &tcp->tcp_ip6h->ip6_dst))) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18617
	    !(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18618
		IRE_REFHOLD(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18619
		mutex_exit(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18620
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18621
		boolean_t cached = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18623
		/* force a recheck later on */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18624
		tcp->tcp_ire_ill_check_done = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18626
		TCP_DBGSTAT(tcp_ire_null1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18627
		tcp->tcp_connp->conn_ire_cache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18628
		mutex_exit(&tcp->tcp_connp->conn_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18629
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18630
		/* Release the old ire */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18631
		if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18632
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18633
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18634
		ire = (af == AF_INET) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18635
		    ire_cache_lookup(dst, tcp->tcp_connp->conn_zoneid) :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18636
		    ire_cache_lookup_v6(&tcp->tcp_ip6h->ip6_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18637
		    tcp->tcp_connp->conn_zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18639
		if (ire == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18640
			TCP_STAT(tcp_ire_null);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18641
			goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18642
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18643
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18644
		IRE_REFHOLD_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18645
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18646
		 * Since we are inside the squeue, there cannot be another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18647
		 * thread in TCP trying to set the conn_ire_cache now. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18648
		 * check for IRE_MARK_CONDEMNED ensures that an interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18649
		 * unplumb thread has not yet started cleaning up the conns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18650
		 * Hence we don't need to grab the conn lock.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18651
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18652
		if (!(tcp->tcp_connp->conn_state_flags & CONN_CLOSING)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18653
			rw_enter(&ire->ire_bucket->irb_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18654
			if (!(ire->ire_marks & IRE_MARK_CONDEMNED)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18655
				tcp->tcp_connp->conn_ire_cache = ire;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18656
				cached = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18657
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18658
			rw_exit(&ire->ire_bucket->irb_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18659
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18661
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18662
		 * We can continue to use the ire but since it was not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18663
		 * cached, we should drop the extra reference.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18664
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18665
		if (!cached)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18666
			IRE_REFRELE_NOTR(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18667
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18669
	ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18670
	ASSERT(af != AF_INET || ire->ire_ipversion == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18671
	ASSERT(af == AF_INET || !IN6_IS_ADDR_V4MAPPED(&(ire->ire_addr_v6)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18672
	ASSERT(af == AF_INET || ire->ire_nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18673
	ASSERT(!(ire->ire_type & IRE_BROADCAST));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18674
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18675
	 * If we do support loopback for MDT (which requires modifications
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18676
	 * to the receiving paths), the following assertions should go away,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18677
	 * and we would be sending the Multidata to loopback conn later on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18678
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18679
	ASSERT(!IRE_IS_LOCAL(ire));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18680
	ASSERT(ire->ire_stq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18682
	ill = ire_to_ill(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18683
	ASSERT(ill != NULL);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18684
	ASSERT(!ILL_MDT_CAPABLE(ill) || ill->ill_mdt_capab != NULL);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18686
	if (!tcp->tcp_ire_ill_check_done) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18687
		tcp_ire_ill_check(tcp, ire, ill, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18688
		tcp->tcp_ire_ill_check_done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18689
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18691
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18692
	 * If the underlying interface conditions have changed, or if the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18693
	 * new interface does not support MDT, go back to legacy path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18694
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18695
	if (!ILL_MDT_USABLE(ill) || (ire->ire_flags & RTF_MULTIRT) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18696
		/* don't go through this path anymore for this connection */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18697
		TCP_STAT(tcp_mdt_conn_halted2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18698
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18699
		ip1dbg(("tcp_multisend: disabling MDT for connp %p on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18700
		    "interface %s\n", (void *)tcp->tcp_connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18701
		/* IRE will be released prior to returning */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18702
		goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18705
	if (ill->ill_capabilities & ILL_CAPAB_ZEROCOPY)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18706
		zc_cap = ill->ill_zerocopy_capab;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18707
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18708
	/* go to legacy path if interface doesn't support zerocopy */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18709
	if (tcp->tcp_snd_zcopy_aware && do_tcpzcopy != 2 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18710
	    (zc_cap == NULL || zc_cap->ill_zerocopy_flags == 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18711
		/* IRE will be released prior to returning */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18712
		goto legacy_send_no_md;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18713
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18715
	/* does the interface support hardware checksum offload? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18716
	hwcksum_flags = 0;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18717
	if (ILL_HCKSUM_CAPABLE(ill) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18718
	    (ill->ill_hcksum_capab->ill_hcksum_txflags &
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18719
	    (HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 | HCKSUM_INET_PARTIAL |
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18720
	    HCKSUM_IPHDRCKSUM)) && dohwcksum) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18721
		if (ill->ill_hcksum_capab->ill_hcksum_txflags &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18722
		    HCKSUM_IPHDRCKSUM)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18723
			hwcksum_flags = HCK_IPV4_HDRCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18724
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18725
		if (ill->ill_hcksum_capab->ill_hcksum_txflags &
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18726
		    (HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18727
			hwcksum_flags |= HCK_FULLCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18728
		else if (ill->ill_hcksum_capab->ill_hcksum_txflags &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18729
		    HCKSUM_INET_PARTIAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18730
			hwcksum_flags |= HCK_PARTIALCKSUM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18731
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18732
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18733
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18734
	 * Each header fragment consists of the leading extra space,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18735
	 * followed by the TCP/IP header, and the trailing extra space.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18736
	 * We make sure that each header fragment begins on a 32-bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18737
	 * aligned memory address (tcp_mdt_hdr_head is already 32-bit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18738
	 * aligned in tcp_mdt_update).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18739
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18740
	hdr_frag_sz = roundup((tcp->tcp_mdt_hdr_head + tcp_hdr_len +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18741
	    tcp->tcp_mdt_hdr_tail), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18742
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18743
	/* are we starting from the beginning of data block? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18744
	if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18745
		*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18746
		ASSERT((uintptr_t)MBLKL(*xmit_tail) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18747
		*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18748
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18749
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18750
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18751
	 * Here we create one or more Multidata messages, each made up of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18752
	 * one header buffer and up to N payload buffers.  This entire
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18753
	 * operation is done within two loops:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18754
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18755
	 * The outer loop mostly deals with creating the Multidata message,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18756
	 * as well as the header buffer that gets added to it.  It also
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18757
	 * links the Multidata messages together such that all of them can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18758
	 * be sent down to the lower layer in a single putnext call; this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18759
	 * linking behavior depends on the tcp_mdt_chain tunable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18760
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18761
	 * The inner loop takes an existing Multidata message, and adds
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18762
	 * one or more (up to tcp_mdt_max_pld) payload buffers to it.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18763
	 * packetizes those buffers by filling up the corresponding header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18764
	 * buffer fragments with the proper IP and TCP headers, and by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18765
	 * describing the layout of each packet in the packet descriptors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18766
	 * that get added to the Multidata.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18767
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18768
	do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18769
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18770
		 * If usable send window is too small, or data blocks in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18771
		 * transmit list are smaller than our threshold (i.e. app
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18772
		 * performs large writes followed by small ones), we hand
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18773
		 * off the control over to the legacy path.  Note that we'll
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18774
		 * get back the control once it encounters a large block.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18775
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18776
		if (*usable < mss || (*tail_unsent <= mdt_thres &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18777
		    (*xmit_tail)->b_cont != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18778
		    MBLKL((*xmit_tail)->b_cont) <= mdt_thres)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18779
			/* send down what we've got so far */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18780
			if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18781
				tcp_multisend_data(tcp, ire, ill, md_mp_head,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18782
				    obsegs, obbytes, &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18783
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18784
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18785
			 * Pass control over to tcp_send(), but tell it to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18786
			 * return to us once a large-size transmission is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18787
			 * possible.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18788
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18789
			TCP_STAT(tcp_mdt_legacy_small);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18790
			if ((err = tcp_send(q, tcp, mss, tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18791
			    tcp_tcp_hdr_len, num_sack_blk, usable, snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18792
			    tail_unsent, xmit_tail, local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18793
			    mdt_thres)) <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18794
				/* burst count reached, or alloc failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18795
				IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18796
				return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18797
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18799
			/* tcp_send() may have sent everything, so check */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18800
			if (*usable <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18801
				IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18802
				return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18803
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18805
			TCP_STAT(tcp_mdt_legacy_ret);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18806
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18807
			 * We may have delivered the Multidata, so make sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18808
			 * to re-initialize before the next round.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18809
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18810
			md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18811
			obsegs = obbytes = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18812
			num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18813
			PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18815
			/* are we starting from the beginning of data block? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18816
			if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18817
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18818
				ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18819
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18820
				*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18821
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18822
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18823
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18824
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18825
		 * max_pld limits the number of mblks in tcp's transmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18826
		 * queue that can be added to a Multidata message.  Once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18827
		 * this counter reaches zero, no more additional mblks
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18828
		 * can be added to it.  What happens afterwards depends
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18829
		 * on whether or not we are set to chain the Multidata
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18830
		 * messages.  If we are to link them together, reset
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18831
		 * max_pld to its original value (tcp_mdt_max_pld) and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18832
		 * prepare to create a new Multidata message which will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18833
		 * get linked to md_mp_head.  Else, leave it alone and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18834
		 * let the inner loop break on its own.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18835
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18836
		if (tcp_mdt_chain && max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18837
			PREP_NEW_MULTIDATA();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18838
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18839
		/* adding a payload buffer; re-initialize values */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18840
		if (add_buffer)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18841
			PREP_NEW_PBUF();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18842
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18843
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18844
		 * If we don't have a Multidata, either because we just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18845
		 * (re)entered this outer loop, or after we branched off
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18846
		 * to tcp_send above, setup the Multidata and header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18847
		 * buffer to be used.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18848
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18849
		if (md_mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18850
			int md_hbuflen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18851
			uint32_t start, stuff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18853
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18854
			 * Calculate Multidata header buffer size large enough
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18855
			 * to hold all of the headers that can possibly be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18856
			 * sent at this moment.  We'd rather over-estimate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18857
			 * the size than running out of space; this is okay
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18858
			 * since this buffer is small anyway.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18859
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18860
			md_hbuflen = (howmany(*usable, mss) + 1) * hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18862
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18863
			 * Start and stuff offset for partial hardware
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18864
			 * checksum offload; these are currently for IPv4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18865
			 * For full checksum offload, they are set to zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18866
			 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18867
			if ((hwcksum_flags & HCK_PARTIALCKSUM)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18868
				if (af == AF_INET) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18869
					start = IP_SIMPLE_HDR_LENGTH;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18870
					stuff = IP_SIMPLE_HDR_LENGTH +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18871
					    TCP_CHECKSUM_OFFSET;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18872
				} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18873
					start = IPV6_HDR_LEN;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18874
					stuff = IPV6_HDR_LEN +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18875
					    TCP_CHECKSUM_OFFSET;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18876
				}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18877
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18878
				start = stuff = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18879
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18880
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18881
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18882
			 * Create the header buffer, Multidata, as well as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18883
			 * any necessary attributes (destination address,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18884
			 * SAP and hardware checksum offload) that should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18885
			 * be associated with the Multidata message.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18886
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18887
			ASSERT(cur_hdr_off == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18888
			if ((md_hbuf = allocb(md_hbuflen, BPRI_HI)) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18889
			    ((md_hbuf->b_wptr += md_hbuflen),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18890
			    (mmd = mmd_alloc(md_hbuf, &md_mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18891
			    KM_NOSLEEP)) == NULL) || (tcp_mdt_add_attrs(mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18892
			    /* fastpath mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18893
			    (af == AF_INET) ? ire->ire_dlureq_mp :
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18894
			    ire->ire_nce->nce_res_mp,
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18895
			    /* hardware checksum enabled */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 18896
			    (hwcksum_flags & (HCK_FULLCKSUM|HCK_PARTIALCKSUM)),
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18897
			    /* hardware checksum offsets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18898
			    start, stuff, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18899
			    /* hardware checksum flag */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18900
			    hwcksum_flags) != 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18901
legacy_send:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18902
				if (md_mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18903
					/* Unlink message from the chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18904
					if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18905
						err = (intptr_t)rmvb(md_mp_head,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18906
						    md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18907
						/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18908
						 * We can't assert that rmvb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18909
						 * did not return -1, since we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18910
						 * may get here before linkb
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18911
						 * happens.  We do, however,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18912
						 * check if we just removed the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18913
						 * only element in the list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18914
						 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18915
						if (err == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18916
							md_mp_head = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18917
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18918
					/* md_hbuf gets freed automatically */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18919
					TCP_STAT(tcp_mdt_discarded);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18920
					freeb(md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18921
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18922
					/* Either allocb or mmd_alloc failed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18923
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18924
					if (md_hbuf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18925
						freeb(md_hbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18926
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18928
				/* send down what we've got so far */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18929
				if (md_mp_head != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18930
					tcp_multisend_data(tcp, ire, ill,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18931
					    md_mp_head, obsegs, obbytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18932
					    &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18933
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18934
legacy_send_no_md:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18935
				if (ire != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18936
					IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18937
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18938
				 * Too bad; let the legacy path handle this.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18939
				 * We specify INT_MAX for the threshold, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18940
				 * we gave up with the Multidata processings
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18941
				 * and let the old path have it all.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18942
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18943
				TCP_STAT(tcp_mdt_legacy_all);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18944
				return (tcp_send(q, tcp, mss, tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18945
				    tcp_tcp_hdr_len, num_sack_blk, usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18946
				    snxt, tail_unsent, xmit_tail, local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18947
				    INT_MAX));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18948
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18949
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18950
			/* link to any existing ones, if applicable */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18951
			TCP_STAT(tcp_mdt_allocd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18952
			if (md_mp_head == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18953
				md_mp_head = md_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18954
			} else if (tcp_mdt_chain) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18955
				TCP_STAT(tcp_mdt_linked);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18956
				linkb(md_mp_head, md_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18957
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18958
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18960
		ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18961
		ASSERT(tcp_mdt_chain || md_mp_head->b_cont == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18962
		ASSERT(md_mp != NULL && mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18963
		ASSERT(md_hbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18964
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18965
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18966
		 * Packetize the transmittable portion of the data block;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18967
		 * each data block is essentially added to the Multidata
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18968
		 * as a payload buffer.  We also deal with adding more
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18969
		 * than one payload buffers, which happens when the remaining
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18970
		 * packetized portion of the current payload buffer is less
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18971
		 * than MSS, while the next data block in transmit queue
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18972
		 * has enough data to make up for one.  This "spillover"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18973
		 * case essentially creates a split-packet, where portions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18974
		 * of the packet's payload fragments may span across two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18975
		 * virtually discontiguous address blocks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18976
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18977
		seg_len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18978
		do {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18979
			len = seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18981
			ASSERT(len > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18982
			ASSERT(max_pld >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18983
			ASSERT(!add_buffer || cur_pld_off == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18984
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18985
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18986
			 * First time around for this payload buffer; note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18987
			 * in the case of a spillover, the following has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18988
			 * been done prior to adding the split-packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18989
			 * descriptor to Multidata, and we don't want to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18990
			 * repeat the process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18991
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18992
			if (add_buffer) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18993
				ASSERT(mmd != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18994
				ASSERT(md_pbuf == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18995
				ASSERT(md_pbuf_nxt == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18996
				ASSERT(pbuf_idx == -1 && pbuf_idx_nxt == -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18998
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 18999
				 * Have we reached the limit?  We'd get to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19000
				 * this case when we're not chaining the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19001
				 * Multidata messages together, and since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19002
				 * we're done, terminate this loop.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19003
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19004
				if (max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19005
					break; /* done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19007
				if ((md_pbuf = dupb(*xmit_tail)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19008
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19009
					goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19010
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19011
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19012
				if (IS_VMLOANED_MBLK(md_pbuf) && !zcopy &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19013
				    zc_cap != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19014
					if (!ip_md_zcopy_attr(mmd, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19015
					    zc_cap->ill_zerocopy_flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19016
						freeb(md_pbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19017
						TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19018
						/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19019
						goto legacy_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19020
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19021
					zcopy = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19022
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19024
				md_pbuf->b_rptr += base_pld_off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19025
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19026
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19027
				 * Add a payload buffer to the Multidata; this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19028
				 * operation must not fail, or otherwise our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19029
				 * logic in this routine is broken.  There
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19030
				 * is no memory allocation done by the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19031
				 * routine, so any returned failure simply
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19032
				 * tells us that we've done something wrong.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19033
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19034
				 * A failure tells us that either we're adding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19035
				 * the same payload buffer more than once, or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19036
				 * we're trying to add more buffers than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19037
				 * allowed (max_pld calculation is wrong).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19038
				 * None of the above cases should happen, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19039
				 * we panic because either there's horrible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19040
				 * heap corruption, and/or programming mistake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19041
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19042
				pbuf_idx = mmd_addpldbuf(mmd, md_pbuf);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19043
				if (pbuf_idx < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19044
					cmn_err(CE_PANIC, "tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19045
					    "payload buffer logic error "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19046
					    "detected for tcp %p mmd %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19047
					    "pbuf %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19048
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19049
					    (void *)md_pbuf, pbuf_idx);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19050
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19052
				ASSERT(max_pld > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19053
				--max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19054
				add_buffer = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19055
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19057
			ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19058
			ASSERT(md_pbuf != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19059
			ASSERT(md_pbuf_nxt == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19060
			ASSERT(pbuf_idx != -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19061
			ASSERT(pbuf_idx_nxt == -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19062
			ASSERT(*usable > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19064
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19065
			 * We spillover to the next payload buffer only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19066
			 * if all of the following is true:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19067
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19068
			 *   1. There is not enough data on the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19069
			 *	payload buffer to make up `len',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19070
			 *   2. We are allowed to send `len',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19071
			 *   3. The next payload buffer length is large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19072
			 *	enough to accomodate `spill'.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19073
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19074
			if ((spill = len - *tail_unsent) > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19075
			    *usable >= len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19076
			    MBLKL((*xmit_tail)->b_cont) >= spill &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19077
			    max_pld > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19078
				md_pbuf_nxt = dupb((*xmit_tail)->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19079
				if (md_pbuf_nxt == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19080
					TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19081
					goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19082
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19083
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19084
				if (IS_VMLOANED_MBLK(md_pbuf_nxt) && !zcopy &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19085
				    zc_cap != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19086
					if (!ip_md_zcopy_attr(mmd, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19087
					    zc_cap->ill_zerocopy_flags)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19088
						freeb(md_pbuf_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19089
						TCP_STAT(tcp_mdt_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19090
						/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19091
						goto legacy_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19092
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19093
					zcopy = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19094
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19096
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19097
				 * See comments above on the first call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19098
				 * mmd_addpldbuf for explanation on the panic.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19099
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19100
				pbuf_idx_nxt = mmd_addpldbuf(mmd, md_pbuf_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19101
				if (pbuf_idx_nxt < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19102
					panic("tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19103
					    "next payload buffer logic error "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19104
					    "detected for tcp %p mmd %p "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19105
					    "pbuf %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19106
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19107
					    (void *)md_pbuf_nxt, pbuf_idx_nxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19108
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19110
				ASSERT(max_pld > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19111
				--max_pld;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19112
			} else if (spill > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19113
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19114
				 * If there's a spillover, but the following
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19115
				 * xmit_tail couldn't give us enough octets
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19116
				 * to reach "len", then stop the current
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19117
				 * Multidata creation and let the legacy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19118
				 * tcp_send() path take over.  We don't want
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19119
				 * to send the tiny segment as part of this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19120
				 * Multidata for performance reasons; instead,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19121
				 * we let the legacy path deal with grouping
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19122
				 * it with the subsequent small mblks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19123
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19124
				if (*usable >= len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19125
				    MBLKL((*xmit_tail)->b_cont) < spill) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19126
					max_pld = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19127
					break;	/* done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19128
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19129
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19130
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19131
				 * We can't spillover, and we are near
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19132
				 * the end of the current payload buffer,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19133
				 * so send what's left.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19134
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19135
				ASSERT(*tail_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19136
				len = *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19137
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19139
			/* tail_unsent is negated if there is a spillover */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19140
			*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19141
			*usable -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19142
			ASSERT(*usable >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19144
			if (*usable < mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19145
				seg_len = *usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19146
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19147
			 * Sender SWS avoidance; see comments in tcp_send();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19148
			 * everything else is the same, except that we only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19149
			 * do this here if there is no more data to be sent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19150
			 * following the current xmit_tail.  We don't check
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19151
			 * for 1-byte urgent data because we shouldn't get
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19152
			 * here if TCP_URG_VALID is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19153
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19154
			if (*usable > 0 && *usable < mss &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19155
			    ((md_pbuf_nxt == NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19156
			    (*xmit_tail)->b_cont == NULL) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19157
			    (md_pbuf_nxt != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19158
			    (*xmit_tail)->b_cont->b_cont == NULL)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19159
			    seg_len < (tcp->tcp_max_swnd >> 1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19160
			    (tcp->tcp_unsent -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19161
			    ((*snxt + len) - tcp->tcp_snxt)) > seg_len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19162
			    !tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19163
				if ((*snxt + len) == tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19164
				    (*snxt + len) == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19165
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19166
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19167
				done = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19168
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19169
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19170
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19171
			 * Prime pump for IP's checksumming on our behalf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19172
			 * include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19173
			 * Do this only for software/partial hardware checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19174
			 * offload, as this field gets zeroed out later for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19175
			 * the full hardware checksum offload case.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19176
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19177
			if (!(hwcksum_flags & HCK_FULLCKSUM)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19178
				cksum = len + tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19179
				cksum = (cksum >> 16) + (cksum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19180
				U16_TO_ABE16(cksum, tcp->tcp_tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19181
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19182
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19183
			U32_TO_ABE32(*snxt, tcp->tcp_tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19184
			*snxt += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19186
			tcp->tcp_tcph->th_flags[0] = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19187
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19188
			 * We set the PUSH bit only if TCP has no more buffered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19189
			 * data to be transmitted (or if sender SWS avoidance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19190
			 * takes place), as opposed to setting it for every
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19191
			 * last packet in the burst.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19192
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19193
			if (done ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19194
			    (tcp->tcp_unsent - (*snxt - tcp->tcp_snxt)) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19195
				tcp->tcp_tcph->th_flags[0] |= TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19196
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19197
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19198
			 * Set FIN bit if this is our last segment; snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19199
			 * already includes its length, and it will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19200
			 * be adjusted after this point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19201
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19202
			if (tcp->tcp_valid_bits == TCP_FSS_VALID &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19203
			    *snxt == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19204
				if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19205
					tcp->tcp_tcph->th_flags[0] |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19206
					BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19207
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19208
				if (!tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19209
					tcp->tcp_fin_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19210
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19211
					 * tcp state must be ESTABLISHED
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19212
					 * in order for us to get here in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19213
					 * the first place.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19214
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19215
					tcp->tcp_state = TCPS_FIN_WAIT_1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19217
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19218
					 * Upon returning from this routine,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19219
					 * tcp_wput_data() will set tcp_snxt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19220
					 * to be equal to snxt + tcp_fin_sent.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19221
					 * This is essentially the same as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19222
					 * setting it to tcp_fss + 1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19223
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19224
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19225
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19227
			tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19229
			len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19230
			if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19231
				tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19232
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19233
				tcp->tcp_ip6h->ip6_plen = htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19234
				    ((char *)&tcp->tcp_ip6h[1] -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19235
				    tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19236
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19237
			pkt_info->flags = (PDESC_HBUF_REF | PDESC_PBUF_REF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19239
			/* setup header fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19240
			PDESC_HDR_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19241
			    md_hbuf->b_rptr + cur_hdr_off,	/* base */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19242
			    tcp->tcp_mdt_hdr_head,		/* head room */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19243
			    tcp_hdr_len,			/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19244
			    tcp->tcp_mdt_hdr_tail);		/* tail room */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19245
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19246
			ASSERT(pkt_info->hdr_lim - pkt_info->hdr_base ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19247
			    hdr_frag_sz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19248
			ASSERT(MBLKIN(md_hbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19249
			    (pkt_info->hdr_base - md_hbuf->b_rptr),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19250
			    PDESC_HDRSIZE(pkt_info)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19251
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19252
			/* setup first payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19253
			PDESC_PLD_INIT(pkt_info);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19254
			PDESC_PLD_SPAN_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19255
			    pbuf_idx,				/* index */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19256
			    md_pbuf->b_rptr + cur_pld_off,	/* start */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19257
			    tcp->tcp_last_sent_len);		/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19259
			/* create a split-packet in case of a spillover */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19260
			if (md_pbuf_nxt != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19261
				ASSERT(spill > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19262
				ASSERT(pbuf_idx_nxt > pbuf_idx);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19263
				ASSERT(!add_buffer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19265
				md_pbuf = md_pbuf_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19266
				md_pbuf_nxt = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19267
				pbuf_idx = pbuf_idx_nxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19268
				pbuf_idx_nxt = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19269
				cur_pld_off = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19270
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19271
				/* trim out first payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19272
				PDESC_PLD_SPAN_TRIM(pkt_info, 0, spill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19274
				/* setup second payload fragment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19275
				PDESC_PLD_SPAN_ADD(pkt_info,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19276
				    pbuf_idx,			/* index */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19277
				    md_pbuf->b_rptr,		/* start */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19278
				    spill);			/* len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19280
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19281
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19282
					 * Store the lbolt used for RTT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19283
					 * estimation. We can only record one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19284
					 * timestamp per mblk so we do it when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19285
					 * we reach the end of the payload
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19286
					 * buffer.  Also we only take a new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19287
					 * timestamp sample when the previous
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19288
					 * timed data from the same mblk has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19289
					 * been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19290
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19291
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19292
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19293
					    (mblk_t *)(uintptr_t)first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19294
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19295
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19296
				first_snxt = *snxt - spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19297
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19298
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19299
				 * Advance xmit_tail; usable could be 0 by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19300
				 * the time we got here, but we made sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19301
				 * above that we would only spillover to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19302
				 * the next data block if usable includes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19303
				 * the spilled-over amount prior to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19304
				 * subtraction.  Therefore, we are sure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19305
				 * that xmit_tail->b_cont can't be NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19306
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19307
				ASSERT((*xmit_tail)->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19308
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19309
				ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19310
				    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19311
				*tail_unsent = (int)MBLKL(*xmit_tail) - spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19312
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19313
				cur_pld_off += tcp->tcp_last_sent_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19314
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19315
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19316
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19317
			 * Fill in the header using the template header, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19318
			 * add options such as time-stamp, ECN and/or SACK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19319
			 * as needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19320
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19321
			tcp_fill_header(tcp, pkt_info->hdr_rptr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19322
			    (clock_t)local_time, num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19324
			/* take care of some IP header businesses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19325
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19326
				ipha = (ipha_t *)pkt_info->hdr_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19328
				ASSERT(OK_32PTR((uchar_t *)ipha));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19329
				ASSERT(PDESC_HDRL(pkt_info) >=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19330
				    IP_SIMPLE_HDR_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19331
				ASSERT(ipha->ipha_version_and_hdr_length ==
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19332
				    IP_SIMPLE_HDR_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19334
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19335
				 * Assign ident value for current packet; see
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19336
				 * related comments in ip_wput_ire() about the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19337
				 * contract private interface with clustering
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19338
				 * group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19339
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19340
				clusterwide = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19341
				if (cl_inet_ipident != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19342
					ASSERT(cl_inet_isclusterwide != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19343
					if ((*cl_inet_isclusterwide)(IPPROTO_IP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19344
					    AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19345
					    (uint8_t *)(uintptr_t)src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19346
						ipha->ipha_ident =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19347
						    (*cl_inet_ipident)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19348
						    (IPPROTO_IP, AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19349
						    (uint8_t *)(uintptr_t)src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19350
						    (uint8_t *)(uintptr_t)dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19351
						clusterwide = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19352
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19353
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19355
				if (!clusterwide) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19356
					ipha->ipha_ident = (uint16_t)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19357
					    atomic_add_32_nv(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19358
						&ire->ire_ident, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19359
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19360
#ifndef _BIG_ENDIAN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19361
				ipha->ipha_ident = (ipha->ipha_ident << 8) |
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19362
				    (ipha->ipha_ident >> 8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19363
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19364
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19365
				ip6h = (ip6_t *)pkt_info->hdr_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19366
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19367
				ASSERT(OK_32PTR((uchar_t *)ip6h));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19368
				ASSERT(IPVER(ip6h) == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19369
				ASSERT(ip6h->ip6_nxt == IPPROTO_TCP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19370
				ASSERT(PDESC_HDRL(pkt_info) >=
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19371
				    (IPV6_HDR_LEN + TCP_CHECKSUM_OFFSET +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19372
				    TCP_CHECKSUM_SIZE));
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19373
				ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19375
				if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19376
					rconfirm = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19377
					tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19378
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19379
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19381
			/* at least one payload span, and at most two */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19382
			ASSERT(pkt_info->pld_cnt > 0 && pkt_info->pld_cnt < 3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19383
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19384
			/* add the packet descriptor to Multidata */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19385
			if ((pkt = mmd_addpdesc(mmd, pkt_info, &err,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19386
			    KM_NOSLEEP)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19387
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19388
				 * Any failure other than ENOMEM indicates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19389
				 * that we have passed in invalid pkt_info
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19390
				 * or parameters to mmd_addpdesc, which must
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19391
				 * not happen.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19392
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19393
				 * EINVAL is a result of failure on boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19394
				 * checks against the pkt_info contents.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19395
				 * should not happen, and we panic because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19396
				 * either there's horrible heap corruption,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19397
				 * and/or programming mistake.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19398
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19399
				if (err != ENOMEM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19400
					cmn_err(CE_PANIC, "tcp_multisend: "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19401
					    "pdesc logic error detected for "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19402
					    "tcp %p mmd %p pinfo %p (%d)\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19403
					    (void *)tcp, (void *)mmd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19404
					    (void *)pkt_info, err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19405
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19406
				TCP_STAT(tcp_mdt_addpdescfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19407
				goto legacy_send; /* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19408
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19409
			ASSERT(pkt != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19410
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19411
			/* calculate IP header and TCP checksums */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19412
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19413
				/* calculate pseudo-header checksum */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19414
				cksum = (dst >> 16) + (dst & 0xFFFF) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19415
				    (src >> 16) + (src & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19417
				/* offset for TCP header checksum */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19418
				up = IPH_TCPH_CHECKSUMP(ipha,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19419
				    IP_SIMPLE_HDR_LENGTH);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19420
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19421
				up = (uint16_t *)&ip6h->ip6_src;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19422
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19423
				/* calculate pseudo-header checksum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19424
				cksum = up[0] + up[1] + up[2] + up[3] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19425
				    up[4] + up[5] + up[6] + up[7] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19426
				    up[8] + up[9] + up[10] + up[11] +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19427
				    up[12] + up[13] + up[14] + up[15];
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19428
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19429
				/* Fold the initial sum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19430
				cksum = (cksum & 0xffff) + (cksum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19431
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19432
				up = (uint16_t *)(((uchar_t *)ip6h) +
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19433
				    IPV6_HDR_LEN + TCP_CHECKSUM_OFFSET);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19434
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19435
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19436
			if (hwcksum_flags & HCK_FULLCKSUM) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19437
				/* clear checksum field for hardware */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19438
				*up = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19439
			} else if (hwcksum_flags & HCK_PARTIALCKSUM) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19440
				uint32_t sum;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19441
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19442
				/* pseudo-header checksumming */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19443
				sum = *up + cksum + IP_TCP_CSUM_COMP;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19444
				sum = (sum & 0xFFFF) + (sum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19445
				*up = (sum & 0xFFFF) + (sum >> 16);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19446
			} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19447
				/* software checksumming */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19448
				TCP_STAT(tcp_out_sw_cksum);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19449
				TCP_STAT_UPDATE(tcp_out_sw_cksum_bytes,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19450
				    tcp->tcp_hdr_len + tcp->tcp_last_sent_len);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19451
				*up = IP_MD_CSUM(pkt, tcp->tcp_ip_hdr_len,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19452
				    cksum + IP_TCP_CSUM_COMP);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19453
				if (*up == 0)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19454
					*up = 0xFFFF;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19455
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19456
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19457
			/* IPv4 header checksum */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 19458
			if (af == AF_INET) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19459
				ipha->ipha_fragment_offset_and_flags |=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19460
				    (uint32_t)htons(ire->ire_frag_flag);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19461
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19462
				if (hwcksum_flags & HCK_IPV4_HDRCKSUM) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19463
					ipha->ipha_hdr_checksum = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19464
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19465
					IP_HDR_CKSUM(ipha, cksum,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19466
					    ((uint32_t *)ipha)[0],
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19467
					    ((uint16_t *)ipha)[4]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19468
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19469
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19471
			/* advance header offset */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19472
			cur_hdr_off += hdr_frag_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19474
			obbytes += tcp->tcp_last_sent_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19475
			++obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19476
		} while (!done && *usable > 0 && --num_burst_seg > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19477
		    *tail_unsent > 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19479
		if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19480
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19481
			 * Store the lbolt used for RTT estimation. We can only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19482
			 * record one timestamp per mblk so we do it when we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19483
			 * reach the end of the payload buffer. Also we only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19484
			 * take a new timestamp sample when the previous timed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19485
			 * data from the same mblk has been ack'ed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19486
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19487
			(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19488
			(*xmit_tail)->b_next = (mblk_t *)(uintptr_t)first_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19489
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19491
		ASSERT(*tail_unsent >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19492
		if (*tail_unsent > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19493
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19494
			 * We got here because we broke out of the above
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19495
			 * loop due to of one of the following cases:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19496
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19497
			 *   1. len < adjusted MSS (i.e. small),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19498
			 *   2. Sender SWS avoidance,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19499
			 *   3. max_pld is zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19500
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19501
			 * We are done for this Multidata, so trim our
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19502
			 * last payload buffer (if any) accordingly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19503
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19504
			if (md_pbuf != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19505
				md_pbuf->b_wptr -= *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19506
		} else if (*usable > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19507
			*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19508
			ASSERT((uintptr_t)MBLKL(*xmit_tail) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19509
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19510
			*tail_unsent = (int)MBLKL(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19511
			add_buffer = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19512
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19513
	} while (!done && *usable > 0 && num_burst_seg > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19514
	    (tcp_mdt_chain || max_pld > 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19516
	/* send everything down */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19517
	tcp_multisend_data(tcp, ire, ill, md_mp_head, obsegs, obbytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19518
	    &rconfirm);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19519
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19520
#undef PREP_NEW_MULTIDATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19521
#undef PREP_NEW_PBUF
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19522
#undef IPVER
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19523
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19524
	IRE_REFRELE(ire);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19525
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19526
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19528
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19529
 * A wrapper function for sending one or more Multidata messages down to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19530
 * the module below ip; this routine does not release the reference of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19531
 * IRE (caller does that).  This routine is analogous to tcp_send_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19532
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19533
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19534
tcp_multisend_data(tcp_t *tcp, ire_t *ire, const ill_t *ill, mblk_t *md_mp_head,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19535
    const uint_t obsegs, const uint_t obbytes, boolean_t *rconfirm)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19536
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19537
	uint64_t delta;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19538
	nce_t *nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19539
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19540
	ASSERT(ire != NULL && ill != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19541
	ASSERT(ire->ire_stq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19542
	ASSERT(md_mp_head != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19543
	ASSERT(rconfirm != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19544
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19545
	/* adjust MIBs and IRE timestamp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19546
	TCP_RECORD_TRACE(tcp, md_mp_head, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19547
	tcp->tcp_obsegs += obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19548
	UPDATE_MIB(&tcp_mib, tcpOutDataSegs, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19549
	UPDATE_MIB(&tcp_mib, tcpOutDataBytes, obbytes);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19550
	TCP_STAT_UPDATE(tcp_mdt_pkt_out, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19552
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19553
		TCP_STAT_UPDATE(tcp_mdt_pkt_out_v4, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19554
		UPDATE_MIB(&ip_mib, ipOutRequests, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19555
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19556
		TCP_STAT_UPDATE(tcp_mdt_pkt_out_v6, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19557
		UPDATE_MIB(&ip6_mib, ipv6OutRequests, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19558
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19559
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19560
	ire->ire_ob_pkt_count += obsegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19561
	if (ire->ire_ipif != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19562
		atomic_add_32(&ire->ire_ipif->ipif_ob_pkt_count, obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19563
	ire->ire_last_used_time = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19564
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19565
	/* send it down */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19566
	putnext(ire->ire_stq, md_mp_head);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19567
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19568
	/* we're done for TCP/IPv4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19569
	if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19570
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19572
	nce = ire->ire_nce;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19573
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19574
	ASSERT(nce != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19575
	ASSERT(!(nce->nce_flags & (NCE_F_NONUD|NCE_F_PERMANENT)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19576
	ASSERT(nce->nce_state != ND_INCOMPLETE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19578
	/* reachability confirmation? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19579
	if (*rconfirm) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19580
		nce->nce_last = TICK_TO_MSEC(lbolt64);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19581
		if (nce->nce_state != ND_REACHABLE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19582
			mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19583
			nce->nce_state = ND_REACHABLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19584
			nce->nce_pcnt = ND_MAX_UNICAST_SOLICIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19585
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19586
			(void) untimeout(nce->nce_timeout_id);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19587
			if (ip_debug > 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19588
				/* ip1dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19589
				pr_addr_dbg("tcp_multisend_data: state "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19590
				    "for %s changed to REACHABLE\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19591
				    AF_INET6, &ire->ire_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19592
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19593
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19594
		/* reset transport reachability confirmation */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19595
		*rconfirm = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19596
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19598
	delta =  TICK_TO_MSEC(lbolt64) - nce->nce_last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19599
	ip1dbg(("tcp_multisend_data: delta = %" PRId64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19600
	    " ill_reachable_time = %d \n", delta, ill->ill_reachable_time));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19602
	if (delta > (uint64_t)ill->ill_reachable_time) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19603
		mutex_enter(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19604
		switch (nce->nce_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19605
		case ND_REACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19606
		case ND_STALE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19607
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19608
			 * ND_REACHABLE is identical to ND_STALE in this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19609
			 * specific case. If reachable time has expired for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19610
			 * this neighbor (delta is greater than reachable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19611
			 * time), conceptually, the neighbor cache is no
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19612
			 * longer in REACHABLE state, but already in STALE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19613
			 * state.  So the correct transition here is to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19614
			 * ND_DELAY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19615
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19616
			nce->nce_state = ND_DELAY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19617
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19618
			NDP_RESTART_TIMER(nce, delay_first_probe_time);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19619
			if (ip_debug > 3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19620
				/* ip2dbg */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19621
				pr_addr_dbg("tcp_multisend_data: state "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19622
				    "for %s changed to DELAY\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19623
				    AF_INET6, &ire->ire_addr_v6);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19624
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19625
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19626
		case ND_DELAY:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19627
		case ND_PROBE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19628
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19629
			/* Timers have already started */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19630
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19631
		case ND_UNREACHABLE:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19632
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19633
			 * ndp timer has detected that this nce is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19634
			 * unreachable and initiated deleting this nce
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19635
			 * and all its associated IREs. This is a race
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19636
			 * where we found the ire before it was deleted
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19637
			 * and have just sent out a packet using this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19638
			 * unreachable nce.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19639
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19640
			mutex_exit(&nce->nce_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19641
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19642
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19643
			ASSERT(0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19644
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19645
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19646
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19647
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19648
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19649
 * tcp_send() is called by tcp_wput_data() for non-Multidata transmission
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19650
 * scheme, and returns one of the following:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19651
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19652
 * -1 = failed allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19653
 *  0 = success; burst count reached, or usable send window is too small,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19654
 *      and that we'd rather wait until later before sending again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19655
 *  1 = success; we are called from tcp_multisend(), and both usable send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19656
 *      window and tail_unsent are greater than the MDT threshold, and thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19657
 *      Multidata Transmit should be used instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19658
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19659
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19660
tcp_send(queue_t *q, tcp_t *tcp, const int mss, const int tcp_hdr_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19661
    const int tcp_tcp_hdr_len, const int num_sack_blk, int *usable,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19662
    uint_t *snxt, int *tail_unsent, mblk_t **xmit_tail, mblk_t *local_time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19663
    const int mdt_thres)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19664
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19665
	int num_burst_seg = tcp->tcp_snd_burst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19667
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19668
		struct datab	*db;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19669
		tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19670
		uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19671
		mblk_t		*mp, *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19672
		uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19673
		int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19674
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19675
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19676
		 * If we're called by tcp_multisend(), and the amount of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19677
		 * sendable data as well as the size of current xmit_tail
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19678
		 * is beyond the MDT threshold, return to the caller and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19679
		 * let the large data transmit be done using MDT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19680
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19681
		if (*usable > 0 && *usable > mdt_thres &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19682
		    (*tail_unsent > mdt_thres || (*tail_unsent == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19683
		    MBLKL((*xmit_tail)->b_cont) > mdt_thres))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19684
			ASSERT(tcp->tcp_mdt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19685
			return (1);	/* success; do large send */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19686
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19687
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19688
		if (num_burst_seg-- == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19689
			break;		/* success; burst count reached */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19691
		len = mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19692
		if (len > *usable) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19693
			len = *usable;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19694
			if (len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19695
				/* Terminate the loop */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19696
				break;	/* success; too small */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19697
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19698
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19699
			 * Sender silly-window avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19700
			 * Ignore this if we are going to send a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19701
			 * zero window probe out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19702
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19703
			 * TODO: force data into microscopic window?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19704
			 *	==> (!pushed || (unsent > usable))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19705
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19706
			if (len < (tcp->tcp_max_swnd >> 1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19707
			    (tcp->tcp_unsent - (*snxt - tcp->tcp_snxt)) > len &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19708
			    !((tcp->tcp_valid_bits & TCP_URG_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19709
			    len == 1) && (! tcp->tcp_zero_win_probe)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19710
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19711
				 * If the retransmit timer is not running
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19712
				 * we start it so that we will retransmit
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19713
				 * in the case when the the receiver has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19714
				 * decremented the window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19715
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19716
				if (*snxt == tcp->tcp_snxt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19717
				    *snxt == tcp->tcp_suna) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19718
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19719
					 * We are not supposed to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19720
					 * anything.  So let's wait a little
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19721
					 * bit longer before breaking SWS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19722
					 * avoidance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19723
					 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19724
					 * What should the value be?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19725
					 * Suggestion: MAX(init rexmit time,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19726
					 * tcp->tcp_rto)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19727
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19728
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19729
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19730
				break;	/* success; too small */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19731
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19732
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19733
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19734
		tcph = tcp->tcp_tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19735
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19736
		*usable -= len; /* Approximate - can be adjusted later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19737
		if (*usable > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19738
			tcph->th_flags[0] = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19739
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19740
			tcph->th_flags[0] = (TH_ACK | TH_PUSH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19742
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19743
		 * Prime pump for IP's checksumming on our behalf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19744
		 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19745
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19746
		sum = len + tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19747
		sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19748
		U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19749
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19750
		U32_TO_ABE32(*snxt, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19752
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19753
		 * Branch off to tcp_xmit_mp() if any of the VALID bits is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19754
		 * set.  For the case when TCP_FSS_VALID is the only valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19755
		 * bit (normal active close), branch off only when we think
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19756
		 * that the FIN flag needs to be set.  Note for this case,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19757
		 * that (snxt + len) may not reflect the actual seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19758
		 * as len may be further reduced in tcp_xmit_mp().  If len
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19759
		 * gets modified, we will end up here again.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19760
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19761
		if (tcp->tcp_valid_bits != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19762
		    (tcp->tcp_valid_bits != TCP_FSS_VALID ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19763
		    ((*snxt + len) == tcp->tcp_fss))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19764
			uchar_t		*prev_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19765
			uint32_t	prev_snxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19766
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19767
			if (*tail_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19768
				ASSERT((*xmit_tail)->b_cont != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19769
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19770
				prev_rptr = (*xmit_tail)->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19771
				*tail_unsent = (int)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19772
				    (*xmit_tail)->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19773
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19774
				prev_rptr = (*xmit_tail)->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19775
				(*xmit_tail)->b_rptr = (*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19776
				    *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19777
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19778
			mp = tcp_xmit_mp(tcp, *xmit_tail, len, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19779
			    *snxt, B_FALSE, (uint32_t *)&len, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19780
			/* Restore tcp_snxt so we get amount sent right. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19781
			tcp->tcp_snxt = prev_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19782
			if (prev_rptr == (*xmit_tail)->b_rptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19783
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19784
				 * If the previous timestamp is still in use,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19785
				 * don't stomp on it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19786
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19787
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19788
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19789
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19790
					    (mblk_t *)(uintptr_t)(*snxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19791
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19792
			} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19793
				(*xmit_tail)->b_rptr = prev_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19794
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19795
			if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19796
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19797
			mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19798
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19799
			tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19800
			while (mp1->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19801
				*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19802
				(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19803
				(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19804
				    (mblk_t *)(uintptr_t)(*snxt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19805
				mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19806
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19807
			*snxt += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19808
			*tail_unsent = (*xmit_tail)->b_wptr - mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19809
			BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19810
			BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19811
			UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19812
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19813
			tcp_send_data(tcp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19814
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19815
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19817
		*snxt += len;	/* Adjust later if we don't send all of len */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19818
		BUMP_MIB(&tcp_mib, tcpOutDataSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19819
		UPDATE_MIB(&tcp_mib, tcpOutDataBytes, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19821
		if (*tail_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19822
			/* Are the bytes above us in flight? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19823
			rptr = (*xmit_tail)->b_wptr - *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19824
			if (rptr != (*xmit_tail)->b_rptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19825
				*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19826
				tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19827
				len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19828
				if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19829
					tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19830
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19831
					tcp->tcp_ip6h->ip6_plen =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19832
					    htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19833
					    ((char *)&tcp->tcp_ip6h[1] -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19834
					    tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19835
				mp = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19836
				if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19837
					return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19838
				mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19839
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19840
				 * If the old timestamp is no longer in use,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19841
				 * sample a new timestamp now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19842
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19843
				if ((*xmit_tail)->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19844
					(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19845
					(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19846
					    (mblk_t *)(uintptr_t)(*snxt-len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19847
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19848
				goto must_alloc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19849
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19850
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19851
			*xmit_tail = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19852
			ASSERT((uintptr_t)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19853
			    (*xmit_tail)->b_rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19854
			*tail_unsent = (int)((*xmit_tail)->b_wptr -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19855
			    (*xmit_tail)->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19856
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19858
		(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19859
		(*xmit_tail)->b_next = (mblk_t *)(uintptr_t)(*snxt - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19860
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19861
		*tail_unsent -= len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19862
		tcp->tcp_last_sent_len = (ushort_t)len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19863
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19864
		len += tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19865
		if (tcp->tcp_ipversion == IPV4_VERSION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19866
			tcp->tcp_ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19867
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19868
			tcp->tcp_ip6h->ip6_plen = htons(len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19869
			    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19870
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19871
		mp = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19872
		if (!mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19873
			return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19874
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19875
		len = tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19876
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19877
		 * There are four reasons to allocate a new hdr mblk:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19878
		 *  1) The bytes above us are in use by another packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19879
		 *  2) We don't have good alignment
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19880
		 *  3) The mblk is being shared
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19881
		 *  4) We don't have enough room for a header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19882
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19883
		rptr = mp->b_rptr - len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19884
		if (!OK_32PTR(rptr) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19885
		    ((db = mp->b_datap), db->db_ref != 2) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19886
		    rptr < db->db_base) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19887
			/* NOTE: we assume allocb returns an OK_32PTR */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19889
		must_alloc:;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19890
			mp1 = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19891
			    tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19892
			if (!mp1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19893
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19894
				return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19895
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19896
			mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19897
			mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19898
			/* Leave room for Link Level header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19899
			len = tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19900
			rptr = &mp->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19901
			mp->b_wptr = &rptr[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19902
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19904
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19905
		 * Fill in the header using the template header, and add
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19906
		 * options such as time-stamp, ECN and/or SACK, as needed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19907
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19908
		tcp_fill_header(tcp, rptr, (clock_t)local_time, num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19909
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19910
		mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19911
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19912
		if (*tail_unsent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19913
			int spill = *tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19914
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19915
			mp1 = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19916
			if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19917
				mp1 = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19919
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19920
			 * If we're a little short, tack on more mblks until
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19921
			 * there is no more spillover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19922
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19923
			while (spill < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19924
				mblk_t *nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19925
				int nmpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19926
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19927
				nmp = (*xmit_tail)->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19928
				nmpsz = MBLKL(nmp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19930
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19931
				 * Excess data in mblk; can we split it?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19932
				 * If MDT is enabled for the connection,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19933
				 * keep on splitting as this is a transient
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19934
				 * send path.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19935
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19936
				if (!tcp->tcp_mdt && (spill + nmpsz > 0)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19937
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19938
					 * Don't split if stream head was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19939
					 * told to break up larger writes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19940
					 * into smaller ones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19941
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19942
					if (tcp->tcp_maxpsz > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19943
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19945
					/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19946
					 * Next mblk is less than SMSS/2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19947
					 * rounded up to nearest 64-byte;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19948
					 * let it get sent as part of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19949
					 * next segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19950
					 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19951
					if (tcp->tcp_localnet &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19952
					    !tcp->tcp_cork &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19953
					    (nmpsz < roundup((mss >> 1), 64)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19954
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19955
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19957
				*xmit_tail = nmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19958
				ASSERT((uintptr_t)nmpsz <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19959
				/* Stash for rtt use later */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19960
				(*xmit_tail)->b_prev = local_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19961
				(*xmit_tail)->b_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19962
				    (mblk_t *)(uintptr_t)(*snxt - len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19963
				mp1->b_cont = dupb(*xmit_tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19964
				mp1 = mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19965
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19966
				spill += nmpsz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19967
				if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19968
					*tail_unsent = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19969
					freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19970
					return (-1);	/* out_of_mem */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19971
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19972
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19973
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19974
			/* Trim back any surplus on the last mblk */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19975
			if (spill >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19976
				mp1->b_wptr -= spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19977
				*tail_unsent = spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19978
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19979
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19980
				 * We did not send everything we could in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19981
				 * order to remain within the b_cont limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19982
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19983
				*usable -= spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19984
				*snxt += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19985
				tcp->tcp_last_sent_len += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19986
				UPDATE_MIB(&tcp_mib, tcpOutDataBytes, spill);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19987
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19988
				 * Adjust the checksum
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19989
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19990
				tcph = (tcph_t *)(rptr + tcp->tcp_ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19991
				sum += spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19992
				sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19993
				U16_TO_ABE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19994
				if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19995
					sum = ntohs(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19996
					    ((ipha_t *)rptr)->ipha_length) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19997
					    spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19998
					((ipha_t *)rptr)->ipha_length =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 19999
					    htons(sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20000
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20001
					sum = ntohs(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20002
					    ((ip6_t *)rptr)->ip6_plen) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20003
					    spill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20004
					((ip6_t *)rptr)->ip6_plen =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20005
					    htons(sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20006
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20007
				*tail_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20008
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20009
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20010
		if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20011
			ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20012
			*(uint32_t *)mp->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20013
			tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20014
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20015
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20016
		TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20017
		tcp_send_data(tcp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20018
		BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20019
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20021
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20022
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20024
/* Unlink and return any mblk that looks like it contains a MDT info */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20025
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20026
tcp_mdt_info_mp(mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20027
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20028
	mblk_t	*prev_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20030
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20031
		prev_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20032
		/* no more to process? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20033
		if ((mp = mp->b_cont) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20034
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20035
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20036
		switch (DB_TYPE(mp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20037
		case M_CTL:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20038
			if (*(uint32_t *)mp->b_rptr != MDT_IOC_INFO_UPDATE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20039
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20040
			ASSERT(prev_mp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20041
			prev_mp->b_cont = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20042
			mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20043
			return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20044
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20045
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20046
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20047
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20048
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20049
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20051
/* MDT info update routine, called when IP notifies us about MDT */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20052
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20053
tcp_mdt_update(tcp_t *tcp, ill_mdt_capab_t *mdt_capab, boolean_t first)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20054
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20055
	boolean_t prev_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20056
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20057
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20058
	 * IP is telling us to abort MDT on this connection?  We know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20059
	 * this because the capability is only turned off when IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20060
	 * encounters some pathological cases, e.g. link-layer change
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20061
	 * where the new driver doesn't support MDT, or in situation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20062
	 * where MDT usage on the link-layer has been switched off.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20063
	 * IP would not have sent us the initial MDT_IOC_INFO_UPDATE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20064
	 * if the link-layer doesn't support MDT, and if it does, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20065
	 * will indicate that the feature is to be turned on.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20066
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20067
	prev_state = tcp->tcp_mdt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20068
	tcp->tcp_mdt = (mdt_capab->ill_mdt_on != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20069
	if (!tcp->tcp_mdt && !first) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20070
		TCP_STAT(tcp_mdt_conn_halted3);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20071
		ip1dbg(("tcp_mdt_update: disabling MDT for connp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20072
		    (void *)tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20073
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20074
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20075
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20076
	 * We currently only support MDT on simple TCP/{IPv4,IPv6},
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20077
	 * so disable MDT otherwise.  The checks are done here
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20078
	 * and in tcp_wput_data().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20079
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20080
	if (tcp->tcp_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20081
	    (tcp->tcp_ipversion == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20082
	    tcp->tcp_ip_hdr_len != IP_SIMPLE_HDR_LENGTH) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20083
	    (tcp->tcp_ipversion == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20084
	    tcp->tcp_ip_hdr_len != IPV6_HDR_LEN))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20085
		tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20086
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20087
	if (tcp->tcp_mdt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20088
		if (mdt_capab->ill_mdt_version != MDT_VERSION_2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20089
			cmn_err(CE_NOTE, "tcp_mdt_update: unknown MDT "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20090
			    "version (%d), expected version is %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20091
			    mdt_capab->ill_mdt_version, MDT_VERSION_2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20092
			tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20093
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20094
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20096
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20097
		 * We need the driver to be able to handle at least three
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20098
		 * spans per packet in order for tcp MDT to be utilized.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20099
		 * The first is for the header portion, while the rest are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20100
		 * needed to handle a packet that straddles across two
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20101
		 * virtually non-contiguous buffers; a typical tcp packet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20102
		 * therefore consists of only two spans.  Note that we take
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20103
		 * a zero as "don't care".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20104
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20105
		if (mdt_capab->ill_mdt_span_limit > 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20106
		    mdt_capab->ill_mdt_span_limit < 3) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20107
			tcp->tcp_mdt = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20108
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20109
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20111
		/* a zero means driver wants default value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20112
		tcp->tcp_mdt_max_pld = MIN(mdt_capab->ill_mdt_max_pld,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20113
		    tcp_mdt_max_pbufs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20114
		if (tcp->tcp_mdt_max_pld == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20115
			tcp->tcp_mdt_max_pld = tcp_mdt_max_pbufs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20117
		/* ensure 32-bit alignment */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20118
		tcp->tcp_mdt_hdr_head = roundup(MAX(tcp_mdt_hdr_head_min,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20119
		    mdt_capab->ill_mdt_hdr_head), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20120
		tcp->tcp_mdt_hdr_tail = roundup(MAX(tcp_mdt_hdr_tail_min,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20121
		    mdt_capab->ill_mdt_hdr_tail), 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20123
		if (!first && !prev_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20124
			TCP_STAT(tcp_mdt_conn_resumed2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20125
			ip1dbg(("tcp_mdt_update: reenabling MDT for connp %p\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20126
			    (void *)tcp->tcp_connp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20127
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20128
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20129
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20131
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20132
tcp_ire_ill_check(tcp_t *tcp, ire_t *ire, ill_t *ill, boolean_t check_mdt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20133
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20134
	conn_t *connp = tcp->tcp_connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20135
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20136
	ASSERT(ire != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20137
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20138
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20139
	 * We may be in the fastpath here, and although we essentially do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20140
	 * similar checks as in ip_bind_connected{_v6}/ip_mdinfo_return,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20141
	 * we try to keep things as brief as possible.  After all, these
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20142
	 * are only best-effort checks, and we do more thorough ones prior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20143
	 * to calling tcp_multisend().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20144
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20145
	if (ip_multidata_outbound && check_mdt &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20146
	    !(ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK)) &&
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20147
	    ill != NULL && ILL_MDT_CAPABLE(ill) &&
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20148
	    !CONN_IPSEC_OUT_ENCAPSULATED(connp) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20149
	    !(ire->ire_flags & RTF_MULTIRT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20150
	    !IPP_ENABLED(IPP_LOCAL_OUT) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20151
	    CONN_IS_MD_FASTPATH(connp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20152
		/* Remember the result */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20153
		connp->conn_mdt_ok = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20154
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20155
		ASSERT(ill->ill_mdt_capab != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20156
		if (!ill->ill_mdt_capab->ill_mdt_on) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20157
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20158
			 * If MDT has been previously turned off in the past,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20159
			 * and we currently can do MDT (due to IPQoS policy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20160
			 * removal, etc.) then enable it for this interface.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20161
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20162
			ill->ill_mdt_capab->ill_mdt_on = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20163
			ip1dbg(("tcp_ire_ill_check: connp %p enables MDT for "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20164
			    "interface %s\n", (void *)connp, ill->ill_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20165
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20166
		tcp_mdt_update(tcp, ill->ill_mdt_capab, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20167
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20169
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20170
	 * The goal is to reduce the number of generated tcp segments by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20171
	 * setting the maxpsz multiplier to 0; this will have an affect on
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20172
	 * tcp_maxpsz_set().  With this behavior, tcp will pack more data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20173
	 * into each packet, up to SMSS bytes.  Doing this reduces the number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20174
	 * of outbound segments and incoming ACKs, thus allowing for better
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20175
	 * network and system performance.  In contrast the legacy behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20176
	 * may result in sending less than SMSS size, because the last mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20177
	 * for some packets may have more data than needed to make up SMSS,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20178
	 * and the legacy code refused to "split" it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20179
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20180
	 * We apply the new behavior on following situations:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20181
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20182
	 *   1) Loopback connections,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20183
	 *   2) Connections in which the remote peer is not on local subnet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20184
	 *   3) Local subnet connections over the bge interface (see below).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20185
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20186
	 * Ideally, we would like this behavior to apply for interfaces other
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20187
	 * than bge.  However, doing so would negatively impact drivers which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20188
	 * perform dynamic mapping and unmapping of DMA resources, which are
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20189
	 * increased by setting the maxpsz multiplier to 0 (more mblks per
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20190
	 * packet will be generated by tcp).  The bge driver does not suffer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20191
	 * from this, as it copies the mblks into pre-mapped buffers, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20192
	 * therefore does not require more I/O resources than before.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20193
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20194
	 * Otherwise, this behavior is present on all network interfaces when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20195
	 * the destination endpoint is non-local, since reducing the number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20196
	 * of packets in general is good for the network.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20197
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20198
	 * TODO We need to remove this hard-coded conditional for bge once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20199
	 *	a better "self-tuning" mechanism, or a way to comprehend
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20200
	 *	the driver transmit strategy is devised.  Until the solution
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20201
	 *	is found and well understood, we live with this hack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20202
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20203
	if (!tcp_static_maxpsz &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20204
	    (tcp->tcp_loopback || !tcp->tcp_localnet ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20205
	    (ill->ill_name_length > 3 && bcmp(ill->ill_name, "bge", 3) == 0))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20206
		/* override the default value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20207
		tcp->tcp_maxpsz = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20208
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20209
		ip3dbg(("tcp_ire_ill_check: connp %p tcp_maxpsz %d on "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20210
		    "interface %s\n", (void *)connp, tcp->tcp_maxpsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20211
		    ill != NULL ? ill->ill_name : ipif_loopback_name));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20214
	/* set the stream head parameters accordingly */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20215
	(void) tcp_maxpsz_set(tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20216
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20217
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20218
/* tcp_wput_flush is called by tcp_wput_nondata to handle M_FLUSH messages. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20219
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20220
tcp_wput_flush(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20221
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20222
	uchar_t	fval = *mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20223
	mblk_t	*tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20224
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20226
	/* TODO: How should flush interact with urgent data? */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20227
	if ((fval & FLUSHW) && tcp->tcp_xmit_head &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20228
	    !(tcp->tcp_valid_bits & TCP_URG_VALID)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20229
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20230
		 * Flush only data that has not yet been put on the wire.  If
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20231
		 * we flush data that we have already transmitted, life, as we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20232
		 * know it, may come to an end.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20233
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20234
		tail = tcp->tcp_xmit_tail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20235
		tail->b_wptr -= tcp->tcp_xmit_tail_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20236
		tcp->tcp_xmit_tail_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20237
		tcp->tcp_unsent = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20238
		if (tail->b_wptr != tail->b_rptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20239
			tail = tail->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20240
		if (tail) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20241
			mblk_t **excess = &tcp->tcp_xmit_head;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20242
			for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20243
				mblk_t *mp1 = *excess;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20244
				if (mp1 == tail)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20245
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20246
				tcp->tcp_xmit_tail = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20247
				tcp->tcp_xmit_last = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20248
				excess = &mp1->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20249
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20250
			*excess = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20251
			tcp_close_mpp(&tail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20252
			if (tcp->tcp_snd_zcopy_aware)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20253
				tcp_zcopy_notify(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20254
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20255
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20256
		 * We have no unsent data, so unsent must be less than
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20257
		 * tcp_xmit_lowater, so re-enable flow.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20258
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20259
		if (tcp->tcp_flow_stopped) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20260
			tcp_clrqfull(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20261
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20262
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20263
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20264
	 * TODO: you can't just flush these, you have to increase rwnd for one
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20265
	 * thing.  For another, how should urgent data interact?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20266
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20267
	if (fval & FLUSHR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20268
		*mp->b_rptr = fval & ~FLUSHW;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20269
		/* XXX */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20270
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20271
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20272
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20273
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20274
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20276
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20277
 * tcp_wput_iocdata is called by tcp_wput_nondata to handle all M_IOCDATA
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20278
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20279
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20280
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20281
tcp_wput_iocdata(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20282
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20283
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20284
	STRUCT_HANDLE(strbuf, sb);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20285
	uint16_t port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20286
	queue_t 	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20287
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20288
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20289
	uint32_t	flowinfo = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20290
	int		addrlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20291
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20292
	/* Make sure it is one of ours. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20293
	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20294
	case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20295
	case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20296
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20297
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20298
		CALL_IP_WPUT(tcp->tcp_connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20299
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20300
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20301
	switch (mi_copy_state(q, mp, &mp1)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20302
	case -1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20303
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20304
	case MI_COPY_CASE(MI_COPY_IN, 1):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20305
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20306
	case MI_COPY_CASE(MI_COPY_OUT, 1):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20307
		/* Copy out the strbuf. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20308
		mi_copyout(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20309
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20310
	case MI_COPY_CASE(MI_COPY_OUT, 2):
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20311
		/* All done. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20312
		mi_copy_done(q, mp, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20313
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20314
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20315
		mi_copy_done(q, mp, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20316
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20317
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20318
	/* Check alignment of the strbuf */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20319
	if (!OK_32PTR(mp1->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20320
		mi_copy_done(q, mp, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20321
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20322
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20323
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20324
	STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20325
	    (void *)mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20326
	addrlen = tcp->tcp_family == AF_INET ? sizeof (sin_t) : sizeof (sin6_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20328
	if (STRUCT_FGET(sb, maxlen) < addrlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20329
		mi_copy_done(q, mp, EINVAL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20330
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20331
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20332
	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20333
	case TI_GETMYNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20334
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20335
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20336
				v4addr = tcp->tcp_ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20337
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20338
				/* can't return an address in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20339
				v4addr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20340
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20341
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20342
			/* tcp->tcp_family == AF_INET6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20343
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20344
				IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20345
				    &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20346
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20347
				v6addr = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20348
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20349
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20350
		port = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20351
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20352
	case TI_GETPEERNAME:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20353
		if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20354
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20355
				IN6_V4MAPPED_TO_IPADDR(&tcp->tcp_remote_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20356
				    v4addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20357
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20358
				/* can't return an address in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20359
				v4addr = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20360
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20361
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20362
			/* tcp->tcp_family == AF_INET6) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20363
			v6addr = tcp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20364
			if (tcp->tcp_ipversion == IPV6_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20365
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20366
				 * No flowinfo if tcp->tcp_ipversion is v4.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20367
				 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20368
				 * flowinfo was already initialized to zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20369
				 * where it was declared above, so only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20370
				 * set it if ipversion is v6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20371
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20372
				flowinfo = tcp->tcp_ip6h->ip6_vcf &
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20373
				    ~IPV6_VERS_AND_FLOW_MASK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20374
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20375
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20376
		port = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20377
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20378
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20379
		mi_copy_done(q, mp, EPROTO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20380
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20381
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20382
	mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20383
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20384
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20385
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20386
	if (tcp->tcp_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20387
		sin_t *sin;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20389
		STRUCT_FSET(sb, len, (int)sizeof (sin_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20390
		sin = (sin_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20391
		mp1->b_wptr = (uchar_t *)&sin[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20392
		*sin = sin_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20393
		sin->sin_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20394
		sin->sin_addr.s_addr = v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20395
		sin->sin_port = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20396
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20397
		/* tcp->tcp_family == AF_INET6 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20398
		sin6_t *sin6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20400
		STRUCT_FSET(sb, len, (int)sizeof (sin6_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20401
		sin6 = (sin6_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20402
		mp1->b_wptr = (uchar_t *)&sin6[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20403
		*sin6 = sin6_null;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20404
		sin6->sin6_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20405
		sin6->sin6_flowinfo = flowinfo;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20406
		sin6->sin6_addr = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20407
		sin6->sin6_port = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20408
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20409
	/* Copy out the address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20410
	mi_copyout(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20411
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20412
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20413
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20414
 * tcp_wput_ioctl is called by tcp_wput_nondata() to handle all M_IOCTL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20415
 * messages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20416
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20417
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20418
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20419
tcp_wput_ioctl(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20420
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20421
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20422
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20423
	queue_t	*q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20424
	struct iocblk	*iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20425
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20426
	ASSERT(DB_TYPE(mp) == M_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20427
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20428
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20429
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20430
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20431
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20432
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20433
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20434
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20435
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20436
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20437
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20439
	iocp = (struct iocblk *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20440
	switch (iocp->ioc_cmd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20441
	case TCP_IOC_DEFAULT_Q:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20442
		/* Wants to be the default wq. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20443
		if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20444
			iocp->ioc_error = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20445
			iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20446
			mp->b_datap->db_type = M_IOCACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20447
			qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20448
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20449
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20450
		tcp_def_q_set(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20451
		return;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20452
	case _SIOCSOCKFALLBACK:
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20453
		/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20454
		 * Either sockmod is about to be popped and the socket
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20455
		 * would now be treated as a plain stream, or a module
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20456
		 * is about to be pushed so we could no longer use read-
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20457
		 * side synchronous streams for fused loopback tcp.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20458
		 * Drain any queued data and disable direct sockfs
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20459
		 * interface from now on.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20460
		 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20461
		if (!tcp->tcp_issocket) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20462
			DB_TYPE(mp) = M_IOCNAK;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20463
			iocp->ioc_error = EINVAL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20464
		} else {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20465
#ifdef	_ILP32
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20466
			tcp->tcp_acceptor_id = (t_uscalar_t)RD(q);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20467
#else
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20468
			tcp->tcp_acceptor_id = tcp->tcp_connp->conn_dev;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20469
#endif
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20470
			/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20471
			 * Insert this socket into the acceptor hash.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20472
			 * We might need it for T_CONN_RES message
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20473
			 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20474
			tcp_acceptor_hash_insert(tcp->tcp_acceptor_id, tcp);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20475
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20476
			if (tcp->tcp_fused) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20477
				/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20478
				 * This is a fused loopback tcp; disable
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20479
				 * read-side synchronous streams interface
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20480
				 * and drain any queued data.  It is okay
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20481
				 * to do this for non-synchronous streams
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20482
				 * fused tcp as well.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20483
				 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20484
				tcp_fuse_disable_pair(tcp, B_FALSE);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20485
			}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20486
			tcp->tcp_issocket = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20487
			TCP_STAT(tcp_sock_fallback);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20488
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20489
			DB_TYPE(mp) = M_IOCACK;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20490
			iocp->ioc_error = 0;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20491
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20492
		iocp->ioc_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20493
		iocp->ioc_rval = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20494
		qreply(q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20495
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20496
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20497
	CALL_IP_WPUT(connp, q, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20498
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20499
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20500
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20501
 * This routine is called by tcp_wput() to handle all TPI requests.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20502
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20503
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20504
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20505
tcp_wput_proto(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20506
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20507
	conn_t 	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20508
	tcp_t	*tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20509
	union T_primitives *tprim = (union T_primitives *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20510
	uchar_t *rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20511
	t_scalar_t type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20512
	int len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20513
	cred_t *cr = DB_CREDDEF(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20515
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20516
	 * Try and ASSERT the minimum possible references on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20517
	 * conn early enough. Since we are executing on write side,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20518
	 * the connection is obviously not detached and that means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20519
	 * there is a ref each for TCP and IP. Since we are behind
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20520
	 * the squeue, the minimum references needed are 3. If the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20521
	 * conn is in classifier hash list, there should be an
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20522
	 * extra ref for that (we check both the possibilities).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20523
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20524
	ASSERT((connp->conn_fanout != NULL && connp->conn_ref >= 4) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20525
	    (connp->conn_fanout == NULL && connp->conn_ref >= 3));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20526
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20527
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20528
	ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20529
	if ((mp->b_wptr - rptr) >= sizeof (t_scalar_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20530
		type = ((union T_primitives *)rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20531
		if (type == T_EXDATA_REQ) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20532
			uint32_t msize = msgdsize(mp->b_cont);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20533
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20534
			len = msize - 1;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20535
			if (len < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20536
				freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20537
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20538
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20539
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20540
			 * Try to force urgent data out on the wire.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20541
			 * Even if we have unsent data this will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20542
			 * at least send the urgent flag.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20543
			 * XXX does not handle more flag correctly.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20544
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20545
			len += tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20546
			len += tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20547
			tcp->tcp_urg = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20548
			tcp->tcp_valid_bits |= TCP_URG_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20550
			/* Bypass tcp protocol for fused tcp loopback */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20551
			if (tcp->tcp_fused && tcp_fuse_output(tcp, mp, msize))
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20552
				return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20553
		} else if (type != T_DATA_REQ) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20554
			goto non_urgent_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20555
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20556
		/* TODO: options, flags, ... from user */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20557
		/* Set length to zero for reclamation below */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20558
		tcp_wput_data(tcp, mp->b_cont, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20559
		freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20560
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20561
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20562
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20563
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20564
			    "tcp_wput_proto, dropping one...");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20565
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20566
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20567
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20568
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20570
non_urgent_data:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20572
	switch ((int)tprim->type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20573
	case O_T_BIND_REQ:	/* bind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20574
	case T_BIND_REQ:	/* new semantics bind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20575
		tcp_bind(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20576
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20577
	case T_UNBIND_REQ:	/* unbind request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20578
		tcp_unbind(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20579
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20580
	case O_T_CONN_RES:	/* old connection response XXX */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20581
	case T_CONN_RES:	/* connection response */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20582
		tcp_accept(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20583
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20584
	case T_CONN_REQ:	/* connection request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20585
		tcp_connect(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20586
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20587
	case T_DISCON_REQ:	/* disconnect request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20588
		tcp_disconnect(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20589
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20590
	case T_CAPABILITY_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20591
		tcp_capability_req(tcp, mp);	/* capability request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20592
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20593
	case T_INFO_REQ:	/* information request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20594
		tcp_info_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20595
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20596
	case T_SVR4_OPTMGMT_REQ:	/* manage options req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20597
		/* Only IP is allowed to return meaningful value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20598
		(void) svr4_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20599
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20600
	case T_OPTMGMT_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20601
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20602
		 * Note:  no support for snmpcom_req() through new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20603
		 * T_OPTMGMT_REQ. See comments in ip.c
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20604
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20605
		/* Only IP is allowed to return meaningful value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20606
		(void) tpi_optcom_req(tcp->tcp_wq, mp, cr, &tcp_opt_obj);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20607
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20609
	case T_UNITDATA_REQ:	/* unitdata request */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20610
		tcp_err_ack(tcp, mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20611
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20612
	case T_ORDREL_REQ:	/* orderly release req */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20613
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20615
		if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20616
			tcp_unfuse(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20617
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20618
		if (tcp_xmit_end(tcp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20619
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20620
			 * We were crossing FINs and got a reset from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20621
			 * the other side. Just ignore it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20622
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20623
			if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20624
				(void) strlog(TCP_MOD_ID, 0, 1,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20625
				    SL_ERROR|SL_TRACE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20626
				    "tcp_wput_proto, T_ORDREL_REQ out of "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20627
				    "state %s",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20628
				    tcp_display(tcp, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20629
				    DISP_ADDR_AND_PORT));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20630
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20631
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20632
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20633
	case T_ADDR_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20634
		tcp_addr_req(tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20635
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20636
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20637
		if (tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20638
			(void) strlog(TCP_MOD_ID, 0, 1, SL_ERROR|SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20639
			    "tcp_wput_proto, bogus TPI msg, type %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20640
			    tprim->type);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20641
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20642
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20643
		 * We used to M_ERROR.  Sending TNOTSUPPORT gives the user
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20644
		 * to recover.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20645
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20646
		tcp_err_ack(tcp, mp, TNOTSUPPORT, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20647
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20648
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20649
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20651
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20652
 * The TCP write service routine should never be called...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20653
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20654
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20655
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20656
tcp_wsrv(queue_t *q)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20657
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20658
	TCP_STAT(tcp_wsrv_called);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20659
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20661
/* Non overlapping byte exchanger */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20662
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20663
tcp_xchg(uchar_t *a, uchar_t *b, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20664
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20665
	uchar_t	uch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20667
	while (len-- > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20668
		uch = a[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20669
		a[len] = b[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20670
		b[len] = uch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20671
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20672
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20674
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20675
 * Send out a control packet on the tcp connection specified.  This routine
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20676
 * is typically called where we need a simple ACK or RST generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20677
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20678
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20679
tcp_xmit_ctl(char *str, tcp_t *tcp, uint32_t seq, uint32_t ack, int ctl)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20680
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20681
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20682
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20683
	ipha_t		*ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20684
	ip6_t		*ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20685
	uint32_t	sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20686
	int		tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20687
	int		tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20688
	mblk_t		*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20689
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20690
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20691
	 * Save sum for use in source route later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20692
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20693
	ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20694
	sum = tcp->tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20695
	tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20696
	tcp_ip_hdr_len = tcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20698
	/* If a text string is passed in with the request, pass it to strlog. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20699
	if (str != NULL && tcp->tcp_debug) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20700
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20701
		    "tcp_xmit_ctl: '%s', seq 0x%x, ack 0x%x, ctl 0x%x",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20702
		    str, seq, ack, ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20703
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20704
	mp = allocb(tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH + tcp_wroff_xtra,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20705
	    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20706
	if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20707
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20708
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20709
	rptr = &mp->b_rptr[tcp_wroff_xtra];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20710
	mp->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20711
	mp->b_wptr = &rptr[tcp_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20712
	bcopy(tcp->tcp_iphc, rptr, tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20714
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20715
		ipha = (ipha_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20716
		ipha->ipha_length = htons(tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20717
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20718
		ip6h = (ip6_t *)rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20719
		ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20720
		ip6h->ip6_plen = htons(tcp->tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20721
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20722
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20723
	tcph = (tcph_t *)&rptr[tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20724
	tcph->th_flags[0] = (uint8_t)ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20725
	if (ctl & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20726
		BUMP_MIB(&tcp_mib, tcpOutRsts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20727
		BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20728
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20729
		 * Don't send TSopt w/ TH_RST packets per RFC 1323.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20730
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20731
		if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20732
		    tcp->tcp_state > TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20733
			mp->b_wptr = &rptr[tcp_hdr_len - TCPOPT_REAL_TS_LEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20734
			*(mp->b_wptr) = TCPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20735
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20736
				ipha->ipha_length = htons(tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20737
				    TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20738
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20739
				ip6h->ip6_plen = htons(ntohs(ip6h->ip6_plen) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20740
				    TCPOPT_REAL_TS_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20741
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20742
			tcph->th_offset_and_rsrvd[0] -= (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20743
			sum -= TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20744
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20745
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20746
	if (ctl & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20747
		if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20748
			U32_TO_BE32(lbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20749
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20750
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20751
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20752
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20754
		/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20755
		U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20756
		    tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20757
		tcp->tcp_rack = ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20758
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20759
		BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20760
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20761
	BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20762
	U32_TO_BE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20763
	U32_TO_BE32(ack, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20764
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20765
	 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20766
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20767
	sum = (sum >> 16) + (sum & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20768
	U16_TO_BE16(sum, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20769
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20770
	tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20771
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20772
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20773
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20774
 * If this routine returns B_TRUE, TCP can generate a RST in response
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20775
 * to a segment.  If it returns B_FALSE, TCP should not respond.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20776
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20777
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20778
tcp_send_rst_chk(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20779
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20780
	clock_t	now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20781
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20782
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20783
	 * TCP needs to protect itself from generating too many RSTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20784
	 * This can be a DoS attack by sending us random segments
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20785
	 * soliciting RSTs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20786
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20787
	 * What we do here is to have a limit of tcp_rst_sent_rate RSTs
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20788
	 * in each 1 second interval.  In this way, TCP still generate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20789
	 * RSTs in normal cases but when under attack, the impact is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20790
	 * limited.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20791
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20792
	if (tcp_rst_sent_rate_enabled != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20793
		now = lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20794
		/* lbolt can wrap around. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20795
		if ((tcp_last_rst_intrvl > now) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20796
		    (TICK_TO_MSEC(now - tcp_last_rst_intrvl) > 1*SECONDS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20797
			tcp_last_rst_intrvl = now;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20798
			tcp_rst_cnt = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20799
		} else if (++tcp_rst_cnt > tcp_rst_sent_rate) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20800
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20801
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20802
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20803
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20804
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20805
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20806
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20807
 * Send down the advice IP ioctl to tell IP to mark an IRE temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20808
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20809
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20810
tcp_ip_ire_mark_advice(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20811
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20812
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20813
	ipic_t *ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20815
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20816
		mp = tcp_ip_advise_mblk(&tcp->tcp_ipha->ipha_dst, IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20817
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20818
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20819
		mp = tcp_ip_advise_mblk(&tcp->tcp_ip6h->ip6_dst, IPV6_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20820
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20821
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20822
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20823
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20824
	ipic->ipic_ire_marks |= IRE_MARK_TEMPORARY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20825
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20826
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20827
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20828
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20829
 * Return an IP advice ioctl mblk and set ipic to be the pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20830
 * to the advice structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20831
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20832
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20833
tcp_ip_advise_mblk(void *addr, int addr_len, ipic_t **ipic)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20834
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20835
	struct iocblk *ioc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20836
	mblk_t *mp, *mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20837
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20838
	mp = allocb(sizeof (ipic_t) + addr_len, BPRI_HI);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20839
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20840
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20841
	bzero(mp->b_rptr, sizeof (ipic_t) + addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20842
	*ipic = (ipic_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20843
	(*ipic)->ipic_cmd = IP_IOC_IRE_ADVISE_NO_REPLY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20844
	(*ipic)->ipic_addr_offset = sizeof (ipic_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20845
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20846
	bcopy(addr, *ipic + 1, addr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20847
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20848
	(*ipic)->ipic_addr_length = addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20849
	mp->b_wptr = &mp->b_rptr[sizeof (ipic_t) + addr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20850
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20851
	mp1 = mkiocb(IP_IOCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20852
	if (mp1 == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20853
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20854
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20855
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20856
	mp1->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20857
	ioc = (struct iocblk *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20858
	ioc->ioc_count = sizeof (ipic_t) + addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20859
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20860
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20861
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20862
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20863
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20864
 * Generate a reset based on an inbound packet for which there is no active
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20865
 * tcp state that we can find.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20866
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20867
 * IPSEC NOTE : Try to send the reply with the same protection as it came
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20868
 * in.  We still have the ipsec_mp that the packet was attached to. Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20869
 * the packet will go out at the same level of protection as it came in by
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20870
 * converting the IPSEC_IN to IPSEC_OUT.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20871
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20872
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20873
tcp_xmit_early_reset(char *str, mblk_t *mp, uint32_t seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20874
    uint32_t ack, int ctl, uint_t ip_hdr_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20875
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20876
	ipha_t		*ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20877
	ip6_t		*ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20878
	ushort_t	len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20879
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20880
	int		i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20881
	mblk_t		*ipsec_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20882
	boolean_t	mctl_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20883
	ipic_t		*ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20884
	ipaddr_t	v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20885
	in6_addr_t	v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20886
	int		addr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20887
	void		*addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20888
	queue_t		*q = tcp_g_q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20889
	tcp_t		*tcp = Q_TO_TCP(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20891
	if (!tcp_send_rst_chk()) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20892
		tcp_rst_unsent++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20893
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20894
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20895
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20896
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20897
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20898
		ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20899
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20900
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20901
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20902
		ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20903
		mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20904
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20906
	if (str && q && tcp_dbg) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 20907
		(void) strlog(TCP_MOD_ID, 0, 1, SL_TRACE,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20908
		    "tcp_xmit_early_reset: '%s', seq 0x%x, ack 0x%x, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20909
		    "flags 0x%x",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20910
		    str, seq, ack, ctl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20911
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20912
	if (mp->b_datap->db_ref != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20913
		mblk_t *mp1 = copyb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20914
		freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20915
		mp = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20916
		if (!mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20917
			if (mctl_present)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20918
				freeb(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20919
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20920
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20921
			if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20922
				ipsec_mp->b_cont = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20923
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20924
				ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20925
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20926
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20927
	} else if (mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20928
		freemsg(mp->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20929
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20930
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20931
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20932
	 * We skip reversing source route here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20933
	 * (for now we replace all IP options with EOL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20934
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20935
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20936
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20937
		for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20938
			mp->b_rptr[i] = IPOPT_EOL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20939
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20940
		 * Make sure that src address isn't flagrantly invalid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20941
		 * Not all broadcast address checking for the src address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20942
		 * is possible, since we don't know the netmask of the src
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20943
		 * addr.  No check for destination address is done, since
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20944
		 * IP will not pass up a packet with a broadcast dest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20945
		 * address to TCP.  Similar checks are done below for IPv6.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20946
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20947
		if (ipha->ipha_src == 0 || ipha->ipha_src == INADDR_BROADCAST ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20948
		    CLASSD(ipha->ipha_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20949
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20950
			BUMP_MIB(&ip_mib, ipInDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20951
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20952
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20953
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20954
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20956
		if (IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20957
		    IN6_IS_ADDR_MULTICAST(&ip6h->ip6_src)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20958
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20959
			BUMP_MIB(&ip6_mib, ipv6InDiscards);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20960
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20961
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20962
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20963
		/* Remove any extension headers assuming partial overlay */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20964
		if (ip_hdr_len > IPV6_HDR_LEN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20965
			uint8_t *to;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20966
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20967
			to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20968
			ovbcopy(ip6h, to, IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20969
			mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20970
			ip_hdr_len = IPV6_HDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20971
			ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20972
			ip6h->ip6_nxt = IPPROTO_TCP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20973
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20974
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20975
	tcph = (tcph_t *)&mp->b_rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20976
	if (tcph->th_flags[0] & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20977
		freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20978
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20979
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20980
	tcph->th_offset_and_rsrvd[0] = (5 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20981
	len = ip_hdr_len + sizeof (tcph_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20982
	mp->b_wptr = &mp->b_rptr[len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20983
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20984
		ipha->ipha_length = htons(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20985
		/* Swap addresses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20986
		v4addr = ipha->ipha_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20987
		ipha->ipha_src = ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20988
		ipha->ipha_dst = v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20989
		ipha->ipha_ident = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20990
		ipha->ipha_ttl = (uchar_t)tcp_ipv4_ttl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20991
		addr_len = IP_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20992
		addr = &v4addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20993
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20994
		/* No ip6i_t in this case */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20995
		ip6h->ip6_plen = htons(len - IPV6_HDR_LEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20996
		/* Swap addresses */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20997
		v6addr = ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20998
		ip6h->ip6_src = ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 20999
		ip6h->ip6_dst = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21000
		ip6h->ip6_hops = (uchar_t)tcp_ipv6_hoplimit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21001
		addr_len = IPV6_ADDR_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21002
		addr = &v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21003
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21004
	tcp_xchg(tcph->th_fport, tcph->th_lport, 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21005
	U32_TO_BE32(ack, tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21006
	U32_TO_BE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21007
	U16_TO_BE16(0, tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21008
	U16_TO_BE16(sizeof (tcph_t), tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21009
	tcph->th_flags[0] = (uint8_t)ctl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21010
	if (ctl & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21011
		BUMP_MIB(&tcp_mib, tcpOutRsts);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21012
		BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21013
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21014
	if (mctl_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21015
		ipsec_in_t *ii = (ipsec_in_t *)ipsec_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21016
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21017
		ASSERT(ii->ipsec_in_type == IPSEC_IN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21018
		if (!ipsec_in_to_out(ipsec_mp, ipha, ip6h)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21019
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21020
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21021
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21022
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21023
	 * NOTE:  one might consider tracing a TCP packet here, but
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21024
	 * this function has no active TCP state nd no tcp structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21025
	 * which has trace buffer.  If we traced here, we would have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21026
	 * to keep a local trace buffer in tcp_record_trace().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21027
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21028
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21030
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21031
	 * Tell IP to mark the IRE used for this destination temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21032
	 * This way, we can limit our exposure to DoS attack because IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21033
	 * creates an IRE for each destination.  If there are too many,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21034
	 * the time to do any routing lookup will be extremely long.  And
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21035
	 * the lookup can be in interrupt context.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21036
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21037
	 * Note that in normal circumstances, this marking should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21038
	 * affect anything.  It would be nice if only 1 message is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21039
	 * needed to inform IP that the IRE created for this RST should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21040
	 * not be added to the cache table.  But there is currently
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21041
	 * not such communication mechanism between TCP and IP.  So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21042
	 * the best we can do now is to send the advice ioctl to IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21043
	 * to mark the IRE temporary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21044
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21045
	if ((mp = tcp_ip_advise_mblk(addr, addr_len, &ipic)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21046
		ipic->ipic_ire_marks |= IRE_MARK_TEMPORARY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21047
		CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21048
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21049
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21051
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21052
 * Initiate closedown sequence on an active connection.  (May be called as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21053
 * writer.)  Return value zero for OK return, non-zero for error return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21054
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21055
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21056
tcp_xmit_end(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21057
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21058
	ipic_t	*ipic;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21059
	mblk_t	*mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21061
	if (tcp->tcp_state < TCPS_SYN_RCVD ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21062
	    tcp->tcp_state > TCPS_CLOSE_WAIT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21063
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21064
		 * Invalid state, only states TCPS_SYN_RCVD,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21065
		 * TCPS_ESTABLISHED and TCPS_CLOSE_WAIT are valid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21066
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21067
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21068
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21069
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21070
	tcp->tcp_fss = tcp->tcp_snxt + tcp->tcp_unsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21071
	tcp->tcp_valid_bits |= TCP_FSS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21072
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21073
	 * If there is nothing more unsent, send the FIN now.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21074
	 * Otherwise, it will go out with the last segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21075
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21076
	if (tcp->tcp_unsent == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21077
		mp = tcp_xmit_mp(tcp, NULL, 0, NULL, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21078
		    tcp->tcp_fss, B_FALSE, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21079
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21080
		if (mp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21081
			TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21082
			tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21083
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21084
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21085
			 * Couldn't allocate msg.  Pretend we got it out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21086
			 * Wait for rexmit timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21087
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21088
			tcp->tcp_snxt = tcp->tcp_fss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21089
			TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21090
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21091
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21092
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21093
		 * If needed, update tcp_rexmit_snxt as tcp_snxt is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21094
		 * changed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21095
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21096
		if (tcp->tcp_rexmit && tcp->tcp_rexmit_nxt == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21097
			tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21098
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21099
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21100
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21101
		 * If tcp->tcp_cork is set, then the data will not get sent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21102
		 * so we have to check that and unset it first.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21103
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21104
		if (tcp->tcp_cork)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21105
			tcp->tcp_cork = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21106
		tcp_wput_data(tcp, NULL, B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21107
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21109
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21110
	 * If TCP does not get enough samples of RTT or tcp_rtt_updates
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21111
	 * is 0, don't update the cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21112
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21113
	if (tcp_rtt_updates == 0 || tcp->tcp_rtt_update < tcp_rtt_updates)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21114
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21116
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21117
	 * NOTE: should not update if source routes i.e. if tcp_remote if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21118
	 * different from the destination.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21119
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21120
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21121
		if (tcp->tcp_remote !=  tcp->tcp_ipha->ipha_dst) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21122
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21123
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21124
		mp = tcp_ip_advise_mblk(&tcp->tcp_ipha->ipha_dst, IP_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21125
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21126
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21127
		if (!(IN6_ARE_ADDR_EQUAL(&tcp->tcp_remote_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21128
		    &tcp->tcp_ip6h->ip6_dst))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21129
			return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21130
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21131
		mp = tcp_ip_advise_mblk(&tcp->tcp_ip6h->ip6_dst, IPV6_ADDR_LEN,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21132
		    &ipic);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21133
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21134
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21135
	/* Record route attributes in the IRE for use by future connections. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21136
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21137
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21139
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21140
	 * We do not have a good algorithm to update ssthresh at this time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21141
	 * So don't do any update.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21142
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21143
	ipic->ipic_rtt = tcp->tcp_rtt_sa;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21144
	ipic->ipic_rtt_sd = tcp->tcp_rtt_sd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21146
	CALL_IP_WPUT(tcp->tcp_connp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21147
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21148
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21150
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21151
 * Generate a "no listener here" RST in response to an "unknown" segment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21152
 * Note that we are reusing the incoming mp to construct the outgoing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21153
 * RST.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21154
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21155
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21156
tcp_xmit_listeners_reset(mblk_t *mp, uint_t ip_hdr_len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21157
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21158
	uchar_t		*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21159
	uint32_t	seg_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21160
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21161
	uint32_t	seg_seq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21162
	uint32_t	seg_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21163
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21164
	mblk_t		*ipsec_mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21165
	ipha_t 		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21166
	ip6_t 		*ip6h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21167
	boolean_t	mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21168
	boolean_t	check = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21169
	boolean_t	policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21170
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21171
	TCP_STAT(tcp_no_listener);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21173
	ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21174
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21175
	if (mp->b_datap->db_type == M_CTL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21176
		ipsec_in_t *ii;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21177
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21178
		mctl_present = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21179
		mp = mp->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21180
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21181
		ii = (ipsec_in_t *)ipsec_mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21182
		ASSERT(ii->ipsec_in_type == IPSEC_IN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21183
		if (ii->ipsec_in_dont_check) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21184
			check = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21185
			if (!ii->ipsec_in_secure) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21186
				freeb(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21187
				mctl_present = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21188
				ipsec_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21189
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21190
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21191
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21193
	if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21194
		policy_present = ipsec_inbound_v4_policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21195
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21196
		ip6h = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21197
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21198
		policy_present = ipsec_inbound_v6_policy_present;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21199
		ipha = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21200
		ip6h = (ip6_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21201
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21203
	if (check && policy_present) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21204
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21205
		 * The conn_t parameter is NULL because we already know
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21206
		 * nobody's home.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21207
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21208
		ipsec_mp = ipsec_check_global_policy(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21209
			ipsec_mp, (conn_t *)NULL, ipha, ip6h, mctl_present);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21210
		if (ipsec_mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21211
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21214
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21215
	rptr = mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21217
	tcph = (tcph_t *)&rptr[ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21218
	seg_seq = BE32_TO_U32(tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21219
	seg_ack = BE32_TO_U32(tcph->th_ack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21220
	flags = tcph->th_flags[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21222
	seg_len = msgdsize(mp) - (TCP_HDR_LENGTH(tcph) + ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21223
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21224
		freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21225
	} else if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21226
		tcp_xmit_early_reset("no tcp, reset",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21227
		    ipsec_mp, seg_ack, 0, TH_RST, ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21228
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21229
		if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21230
			seg_len++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21231
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21232
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21233
			 * Here we violate the RFC.  Note that a normal
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21234
			 * TCP will never send a segment without the ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21235
			 * flag, except for RST or SYN segment.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21236
			 * segment is neither.  Just drop it on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21237
			 * floor.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21238
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21239
			freemsg(ipsec_mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21240
			tcp_rst_unsent++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21241
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21242
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21244
		tcp_xmit_early_reset("no tcp, reset/ack",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21245
		    ipsec_mp, 0, seg_seq + seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21246
		    TH_RST | TH_ACK, ip_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21247
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21248
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21249
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21250
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21251
 * tcp_xmit_mp is called to return a pointer to an mblk chain complete with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21252
 * ip and tcp header ready to pass down to IP.  If the mp passed in is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21253
 * non-NULL, then up to max_to_send bytes of data will be dup'ed off that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21254
 * mblk. (If sendall is not set the dup'ing will stop at an mblk boundary
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21255
 * otherwise it will dup partial mblks.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21256
 * Otherwise, an appropriate ACK packet will be generated.  This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21257
 * routine is not usually called to send new data for the first time.  It
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21258
 * is mostly called out of the timer for retransmits, and to generate ACKs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21259
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21260
 * If offset is not NULL, the returned mblk chain's first mblk's b_rptr will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21261
 * be adjusted by *offset.  And after dupb(), the offset and the ending mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21262
 * of the original mblk chain will be returned in *offset and *end_mp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21263
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21264
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21265
tcp_xmit_mp(tcp_t *tcp, mblk_t *mp, int32_t max_to_send, int32_t *offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21266
    mblk_t **end_mp, uint32_t seq, boolean_t sendall, uint32_t *seg_len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21267
    boolean_t rexmit)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21268
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21269
	int	data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21270
	int32_t	off = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21271
	uint_t	flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21272
	mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21273
	mblk_t	*mp2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21274
	uchar_t	*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21275
	tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21276
	int32_t	num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21277
	int32_t	sack_opt_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21279
	/* Allocate for our maximum TCP header + link-level */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21280
	mp1 = allocb(tcp->tcp_ip_hdr_len + TCP_MAX_HDR_LENGTH + tcp_wroff_xtra,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21281
	    BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21282
	if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21283
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21284
	data_length = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21285
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21286
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21287
	 * Note that tcp_mss has been adjusted to take into account the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21288
	 * timestamp option if applicable.  Because SACK options do not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21289
	 * appear in every TCP segments and they are of variable lengths,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21290
	 * they cannot be included in tcp_mss.  Thus we need to calculate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21291
	 * the actual segment length when we need to send a segment which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21292
	 * includes SACK options.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21293
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21294
	if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21295
		num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21296
		    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21297
		sack_opt_len = num_sack_blk * sizeof (sack_blk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21298
		    TCPOPT_NOP_LEN * 2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21299
		if (max_to_send + sack_opt_len > tcp->tcp_mss)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21300
			max_to_send -= sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21301
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21302
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21303
	if (offset != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21304
		off = *offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21305
		/* We use offset as an indicator that end_mp is not NULL. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21306
		*end_mp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21307
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21308
	for (mp2 = mp1; mp && data_length != max_to_send; mp = mp->b_cont) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21309
		/* This could be faster with cooperation from downstream */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21310
		if (mp2 != mp1 && !sendall &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21311
		    data_length + (int)(mp->b_wptr - mp->b_rptr) >
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21312
		    max_to_send)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21313
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21314
			 * Don't send the next mblk since the whole mblk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21315
			 * does not fit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21316
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21317
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21318
		mp2->b_cont = dupb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21319
		mp2 = mp2->b_cont;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21320
		if (!mp2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21321
			freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21322
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21323
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21324
		mp2->b_rptr += off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21325
		ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21326
		    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21328
		data_length += (int)(mp2->b_wptr - mp2->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21329
		if (data_length > max_to_send) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21330
			mp2->b_wptr -= data_length - max_to_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21331
			data_length = max_to_send;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21332
			off = mp2->b_wptr - mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21333
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21334
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21335
			off = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21336
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21337
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21338
	if (offset != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21339
		*offset = off;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21340
		*end_mp = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21341
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21342
	if (seg_len != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21343
		*seg_len = data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21344
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21346
	/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21347
	U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21348
	    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21349
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21350
	rptr = mp1->b_rptr + tcp_wroff_xtra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21351
	mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21352
	mp1->b_wptr = rptr + tcp->tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21353
	bcopy(tcp->tcp_iphc, rptr, tcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21354
	tcph = (tcph_t *)&rptr[tcp->tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21355
	U32_TO_ABE32(seq, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21357
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21358
	 * Use tcp_unsent to determine if the PUSH bit should be used assumes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21359
	 * that this function was called from tcp_wput_data. Thus, when called
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21360
	 * to retransmit data the setting of the PUSH bit may appear some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21361
	 * what random in that it might get set when it should not. This
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21362
	 * should not pose any performance issues.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21363
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21364
	if (data_length != 0 && (tcp->tcp_unsent == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21365
	    tcp->tcp_unsent == data_length)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21366
		flags = TH_ACK | TH_PUSH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21367
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21368
		flags = TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21369
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21370
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21371
	if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21372
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21373
			flags |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21375
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21376
		 * Only set ECT bit and ECN_CWR if a segment contains new data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21377
		 * There is no TCP flow control for non-data segments, and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21378
		 * only data segment is transmitted reliably.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21379
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21380
		if (data_length > 0 && !rexmit) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21381
			SET_ECT(tcp, rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21382
			if (tcp->tcp_cwr && !tcp->tcp_ecn_cwr_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21383
				flags |= TH_CWR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21384
				tcp->tcp_ecn_cwr_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21385
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21386
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21387
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21388
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21389
	if (tcp->tcp_valid_bits) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21390
		uint32_t u1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21392
		if ((tcp->tcp_valid_bits & TCP_ISS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21393
		    seq == tcp->tcp_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21394
			uchar_t	*wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21395
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21396
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21397
			 * If TCP_ISS_VALID and the seq number is tcp_iss,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21398
			 * TCP can only be in SYN-SENT, SYN-RCVD or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21399
			 * FIN-WAIT-1 state.  It can be FIN-WAIT-1 if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21400
			 * our SYN is not ack'ed but the app closes this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21401
			 * TCP connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21402
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21403
			ASSERT(tcp->tcp_state == TCPS_SYN_SENT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21404
			    tcp->tcp_state == TCPS_SYN_RCVD ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21405
			    tcp->tcp_state == TCPS_FIN_WAIT_1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21407
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21408
			 * Tack on the MSS option.  It is always needed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21409
			 * for both active and passive open.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21410
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21411
			 * MSS option value should be interface MTU - MIN
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21412
			 * TCP/IP header according to RFC 793 as it means
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21413
			 * the maximum segment size TCP can receive.  But
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21414
			 * to get around some broken middle boxes/end hosts
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21415
			 * out there, we allow the option value to be the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21416
			 * same as the MSS option size on the peer side.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21417
			 * In this way, the other side will not send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21418
			 * anything larger than they can receive.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21419
			 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21420
			 * Note that for SYN_SENT state, the ndd param
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21421
			 * tcp_use_smss_as_mss_opt has no effect as we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21422
			 * don't know the peer's MSS option value. So
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21423
			 * the only case we need to take care of is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21424
			 * SYN_RCVD state, which is done later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21425
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21426
			wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21427
			wptr[0] = TCPOPT_MAXSEG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21428
			wptr[1] = TCPOPT_MAXSEG_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21429
			wptr += 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21430
			u1 = tcp->tcp_if_mtu -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21431
			    (tcp->tcp_ipversion == IPV4_VERSION ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21432
			    IP_SIMPLE_HDR_LENGTH : IPV6_HDR_LEN) -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21433
			    TCP_MIN_HEADER_LENGTH;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21434
			U16_TO_BE16(u1, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21435
			mp1->b_wptr = wptr + 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21436
			/* Update the offset to cover the additional word */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21437
			tcph->th_offset_and_rsrvd[0] += (1 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21438
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21439
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21440
			 * Note that the following way of filling in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21441
			 * TCP options are not optimal.  Some NOPs can
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21442
			 * be saved.  But there is no need at this time
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21443
			 * to optimize it.  When it is needed, we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21444
			 * do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21445
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21446
			switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21447
			case TCPS_SYN_SENT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21448
				flags = TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21449
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21450
				if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21451
					uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21453
					wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21454
					wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21455
					wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21456
					wptr[2] = TCPOPT_TSTAMP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21457
					wptr[3] = TCPOPT_TSTAMP_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21458
					wptr += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21459
					U32_TO_BE32(llbolt, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21460
					wptr += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21461
					ASSERT(tcp->tcp_ts_recent == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21462
					U32_TO_BE32(0L, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21463
					mp1->b_wptr += TCPOPT_REAL_TS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21464
					tcph->th_offset_and_rsrvd[0] +=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21465
					    (3 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21466
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21468
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21469
				 * Set up all the bits to tell other side
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21470
				 * we are ECN capable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21471
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21472
				if (tcp->tcp_ecn_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21473
					flags |= (TH_ECE | TH_CWR);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21474
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21475
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21476
			case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21477
				flags |= TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21478
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21479
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21480
				 * Reset the MSS option value to be SMSS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21481
				 * We should probably add back the bytes
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21482
				 * for timestamp option and IPsec.  We
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21483
				 * don't do that as this is a workaround
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21484
				 * for broken middle boxes/end hosts, it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21485
				 * is better for us to be more cautious.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21486
				 * They may not take these things into
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21487
				 * account in their SMSS calculation.  Thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21488
				 * the peer's calculated SMSS may be smaller
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21489
				 * than what it can be.  This should be OK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21490
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21491
				if (tcp_use_smss_as_mss_opt) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21492
					u1 = tcp->tcp_mss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21493
					U16_TO_BE16(u1, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21494
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21496
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21497
				 * If the other side is ECN capable, reply
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21498
				 * that we are also ECN capable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21499
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21500
				if (tcp->tcp_ecn_ok)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21501
					flags |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21502
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21503
			default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21504
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21505
				 * The above ASSERT() makes sure that this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21506
				 * must be FIN-WAIT-1 state.  Our SYN has
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21507
				 * not been ack'ed so retransmit it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21508
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21509
				flags |= TH_SYN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21510
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21511
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21513
			if (tcp->tcp_snd_ws_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21514
				wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21515
				wptr[0] =  TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21516
				wptr[1] =  TCPOPT_WSCALE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21517
				wptr[2] =  TCPOPT_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21518
				wptr[3] = (uchar_t)tcp->tcp_rcv_ws;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21519
				mp1->b_wptr += TCPOPT_REAL_WS_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21520
				tcph->th_offset_and_rsrvd[0] += (1 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21521
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21522
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21523
			if (tcp->tcp_snd_sack_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21524
				wptr = mp1->b_wptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21525
				wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21526
				wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21527
				wptr[2] = TCPOPT_SACK_PERMITTED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21528
				wptr[3] = TCPOPT_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21529
				mp1->b_wptr += TCPOPT_REAL_SACK_OK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21530
				tcph->th_offset_and_rsrvd[0] += (1 << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21531
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21532
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21533
			/* allocb() of adequate mblk assures space */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21534
			ASSERT((uintptr_t)(mp1->b_wptr - mp1->b_rptr) <=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21535
			    (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21536
			u1 = (int)(mp1->b_wptr - mp1->b_rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21537
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21538
			 * Get IP set to checksum on our behalf
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21539
			 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21540
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21541
			u1 += tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21542
			u1 = (u1 >> 16) + (u1 & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21543
			U16_TO_BE16(u1, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21544
			BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21545
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21546
		if ((tcp->tcp_valid_bits & TCP_FSS_VALID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21547
		    (seq + data_length) == tcp->tcp_fss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21548
			if (!tcp->tcp_fin_acked) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21549
				flags |= TH_FIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21550
				BUMP_MIB(&tcp_mib, tcpOutControl);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21551
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21552
			if (!tcp->tcp_fin_sent) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21553
				tcp->tcp_fin_sent = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21554
				switch (tcp->tcp_state) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21555
				case TCPS_SYN_RCVD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21556
				case TCPS_ESTABLISHED:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21557
					tcp->tcp_state = TCPS_FIN_WAIT_1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21558
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21559
				case TCPS_CLOSE_WAIT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21560
					tcp->tcp_state = TCPS_LAST_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21561
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21562
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21563
				if (tcp->tcp_suna == tcp->tcp_snxt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21564
					TCP_TIMER_RESTART(tcp, tcp->tcp_rto);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21565
				tcp->tcp_snxt = tcp->tcp_fss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21566
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21567
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21568
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21569
		 * Note the trick here.  u1 is unsigned.  When tcp_urg
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21570
		 * is smaller than seq, u1 will become a very huge value.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21571
		 * So the comparison will fail.  Also note that tcp_urp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21572
		 * should be positive, see RFC 793 page 17.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21573
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21574
		u1 = tcp->tcp_urg - seq + TCP_OLD_URP_INTERPRETATION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21575
		if ((tcp->tcp_valid_bits & TCP_URG_VALID) && u1 != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21576
		    u1 < (uint32_t)(64 * 1024)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21577
			flags |= TH_URG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21578
			BUMP_MIB(&tcp_mib, tcpOutUrg);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21579
			U32_TO_ABE16(u1, tcph->th_urp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21580
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21581
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21582
	tcph->th_flags[0] = (uchar_t)flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21583
	tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21584
	tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21585
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21586
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21587
		if (tcp->tcp_state != TCPS_SYN_SENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21588
			uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21589
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21590
			U32_TO_BE32(llbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21591
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21592
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21593
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21594
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21595
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21597
	if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21598
		uchar_t *wptr = (uchar_t *)tcph + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21599
		sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21600
		int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21601
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21602
		wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21603
		wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21604
		wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21605
		wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21606
		    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21607
		wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21609
		tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21610
		for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21611
			U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21612
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21613
			U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21614
			wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21615
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21616
		tcph->th_offset_and_rsrvd[0] += ((num_sack_blk * 2 + 1) << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21617
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21618
	ASSERT((uintptr_t)(mp1->b_wptr - rptr) <= (uintptr_t)INT_MAX);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21619
	data_length += (int)(mp1->b_wptr - rptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21620
	if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21621
		((ipha_t *)rptr)->ipha_length = htons(data_length);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21622
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21623
		ip6_t *ip6 = (ip6_t *)(rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21624
		    (((ip6_t *)rptr)->ip6_nxt == IPPROTO_RAW ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21625
		    sizeof (ip6i_t) : 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21626
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21627
		ip6->ip6_plen = htons(data_length -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21628
		    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21629
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21630
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21631
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21632
	 * Prime pump for IP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21633
	 * Include the adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21634
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21635
	data_length -= tcp->tcp_ip_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21636
	data_length += tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21637
	data_length = (data_length >> 16) + (data_length & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21638
	U16_TO_ABE16(data_length, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21639
	if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21640
		ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21641
		*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21642
		tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21643
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21644
	return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21645
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21647
/* This function handles the push timeout. */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21648
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21649
tcp_push_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21650
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21651
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21652
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21653
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21654
	TCP_DBGSTAT(tcp_push_timer_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21655
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21656
	ASSERT(tcp->tcp_listener == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21657
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21658
	/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21659
	 * We need to stop synchronous streams temporarily to prevent a race
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21660
	 * with tcp_fuse_rrw() or tcp_fusion rinfop().  It is safe to access
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21661
	 * tcp_rcv_list here because those entry points will return right
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21662
	 * away when synchronous streams is stopped.
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21663
	 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21664
	TCP_FUSE_SYNCSTR_STOP(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21665
	tcp->tcp_push_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21666
	if ((tcp->tcp_rcv_list != NULL) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21667
	    (tcp_rcv_drain(tcp->tcp_rq, tcp) == TH_ACK_NEEDED))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21668
		tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt, tcp->tcp_rnxt, TH_ACK);
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 21669
	TCP_FUSE_SYNCSTR_RESUME(tcp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21670
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21672
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21673
 * This function handles delayed ACK timeout.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21674
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21675
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21676
tcp_ack_timer(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21677
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21678
	conn_t	*connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21679
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21680
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21681
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21682
	TCP_DBGSTAT(tcp_ack_timer_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21683
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21684
	tcp->tcp_ack_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21685
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21686
	if (tcp->tcp_fused)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21687
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21689
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21690
	 * Do not send ACK if there is no outstanding unack'ed data.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21691
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21692
	if (tcp->tcp_rnxt == tcp->tcp_rack) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21693
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21694
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21696
	if ((tcp->tcp_rnxt - tcp->tcp_rack) > tcp->tcp_mss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21697
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21698
		 * Make sure we don't allow deferred ACKs to result in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21699
		 * timer-based ACKing.  If we have held off an ACK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21700
		 * when there was more than an mss here, and the timer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21701
		 * goes off, we have to worry about the possibility
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21702
		 * that the sender isn't doing slow-start, or is out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21703
		 * of step with us for some other reason.  We fall
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21704
		 * permanently back in the direction of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21705
		 * ACK-every-other-packet as suggested in RFC 1122.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21706
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21707
		if (tcp->tcp_rack_abs_max > 2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21708
			tcp->tcp_rack_abs_max--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21709
		tcp->tcp_rack_cur_max = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21710
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21711
	mp = tcp_ack_mp(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21712
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21713
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21714
		TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_SEND_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21715
		BUMP_LOCAL(tcp->tcp_obsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21716
		BUMP_MIB(&tcp_mib, tcpOutAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21717
		BUMP_MIB(&tcp_mib, tcpOutAckDelayed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21718
		tcp_send_data(tcp, tcp->tcp_wq, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21719
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21720
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21721
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21722
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21723
/* Generate an ACK-only (no data) segment for a TCP endpoint */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21724
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21725
tcp_ack_mp(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21726
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21727
	uint32_t	seq_no;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21728
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21729
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21730
	 * There are a few cases to be considered while setting the sequence no.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21731
	 * Essentially, we can come here while processing an unacceptable pkt
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21732
	 * in the TCPS_SYN_RCVD state, in which case we set the sequence number
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21733
	 * to snxt (per RFC 793), note the swnd wouldn't have been set yet.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21734
	 * If we are here for a zero window probe, stick with suna. In all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21735
	 * other cases, we check if suna + swnd encompasses snxt and set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21736
	 * the sequence number to snxt, if so. If snxt falls outside the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21737
	 * window (the receiver probably shrunk its window), we will go with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21738
	 * suna + swnd, otherwise the sequence no will be unacceptable to the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21739
	 * receiver.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21740
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21741
	if (tcp->tcp_zero_win_probe) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21742
		seq_no = tcp->tcp_suna;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21743
	} else if (tcp->tcp_state == TCPS_SYN_RCVD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21744
		ASSERT(tcp->tcp_swnd == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21745
		seq_no = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21746
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21747
		seq_no = SEQ_GT(tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21748
		    (tcp->tcp_suna + tcp->tcp_swnd)) ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21749
		    (tcp->tcp_suna + tcp->tcp_swnd) : tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21750
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21751
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21752
	if (tcp->tcp_valid_bits) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21753
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21754
		 * For the complex case where we have to send some
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21755
		 * controls (FIN or SYN), let tcp_xmit_mp do it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21756
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21757
		return (tcp_xmit_mp(tcp, NULL, 0, NULL, NULL, seq_no, B_FALSE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21758
		    NULL, B_FALSE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21759
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21760
		/* Generate a simple ACK */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21761
		int	data_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21762
		uchar_t	*rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21763
		tcph_t	*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21764
		mblk_t	*mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21765
		int32_t	tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21766
		int32_t	tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21767
		int32_t	num_sack_blk = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21768
		int32_t sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21769
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21770
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21771
		 * Allocate space for TCP + IP headers
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21772
		 * and link-level header
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21773
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21774
		if (tcp->tcp_snd_sack_ok && tcp->tcp_num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21775
			num_sack_blk = MIN(tcp->tcp_max_sack_blk,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21776
			    tcp->tcp_num_sack_blk);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21777
			sack_opt_len = num_sack_blk * sizeof (sack_blk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21778
			    TCPOPT_NOP_LEN * 2 + TCPOPT_HEADER_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21779
			tcp_hdr_len = tcp->tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21780
			tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len + sack_opt_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21781
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21782
			tcp_hdr_len = tcp->tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21783
			tcp_tcp_hdr_len = tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21784
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21785
		mp1 = allocb(tcp_hdr_len + tcp_wroff_xtra, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21786
		if (!mp1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21787
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21788
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21789
		/* Update the latest receive window size in TCP header. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21790
		U32_TO_ABE16(tcp->tcp_rwnd >> tcp->tcp_rcv_ws,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21791
		    tcp->tcp_tcph->th_win);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21792
		/* copy in prototype TCP + IP header */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21793
		rptr = mp1->b_rptr + tcp_wroff_xtra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21794
		mp1->b_rptr = rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21795
		mp1->b_wptr = rptr + tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21796
		bcopy(tcp->tcp_iphc, rptr, tcp->tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21797
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21798
		tcph = (tcph_t *)&rptr[tcp->tcp_ip_hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21799
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21800
		/* Set the TCP sequence number. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21801
		U32_TO_ABE32(seq_no, tcph->th_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21802
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21803
		/* Set up the TCP flag field. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21804
		tcph->th_flags[0] = (uchar_t)TH_ACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21805
		if (tcp->tcp_ecn_echo_on)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21806
			tcph->th_flags[0] |= TH_ECE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21807
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21808
		tcp->tcp_rack = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21809
		tcp->tcp_rack_cnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21810
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21811
		/* fill in timestamp option if in use */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21812
		if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21813
			uint32_t llbolt = (uint32_t)lbolt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21814
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21815
			U32_TO_BE32(llbolt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21816
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21817
			U32_TO_BE32(tcp->tcp_ts_recent,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21818
			    (char *)tcph+TCP_MIN_HEADER_LENGTH+8);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21819
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21821
		/* Fill in SACK options */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21822
		if (num_sack_blk > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21823
			uchar_t *wptr = (uchar_t *)tcph + tcp->tcp_tcp_hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21824
			sack_blk_t *tmp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21825
			int32_t	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21826
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21827
			wptr[0] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21828
			wptr[1] = TCPOPT_NOP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21829
			wptr[2] = TCPOPT_SACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21830
			wptr[3] = TCPOPT_HEADER_LEN + num_sack_blk *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21831
			    sizeof (sack_blk_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21832
			wptr += TCPOPT_REAL_SACK_LEN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21833
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21834
			tmp = tcp->tcp_sack_list;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21835
			for (i = 0; i < num_sack_blk; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21836
				U32_TO_BE32(tmp[i].begin, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21837
				wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21838
				U32_TO_BE32(tmp[i].end, wptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21839
				wptr += sizeof (tcp_seq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21840
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21841
			tcph->th_offset_and_rsrvd[0] += ((num_sack_blk * 2 + 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21842
			    << 4);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21843
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21844
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21845
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21846
			((ipha_t *)rptr)->ipha_length = htons(tcp_hdr_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21847
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21848
			/* Check for ip6i_t header in sticky hdrs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21849
			ip6_t *ip6 = (ip6_t *)(rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21850
			    (((ip6_t *)rptr)->ip6_nxt == IPPROTO_RAW ?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21851
			    sizeof (ip6i_t) : 0));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21852
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21853
			ip6->ip6_plen = htons(tcp_hdr_len -
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21854
			    ((char *)&tcp->tcp_ip6h[1] - tcp->tcp_iphc));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21855
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21856
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21857
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21858
		 * Prime pump for checksum calculation in IP.  Include the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21859
		 * adjustment for a source route if any.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21860
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21861
		data_length = tcp_tcp_hdr_len + tcp->tcp_sum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21862
		data_length = (data_length >> 16) + (data_length & 0xFFFF);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21863
		U16_TO_ABE16(data_length, tcph->th_sum);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21864
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21865
		if (tcp->tcp_ip_forward_progress) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21866
			ASSERT(tcp->tcp_ipversion == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21867
			*(uint32_t *)mp1->b_rptr  |= IP_FORWARD_PROG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21868
			tcp->tcp_ip_forward_progress = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21869
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21870
		return (mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21871
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21872
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21874
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21875
 * To create a temporary tcp structure for inserting into bind hash list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21876
 * The parameter is assumed to be in network byte order, ready for use.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21877
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21878
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21879
static tcp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21880
tcp_alloc_temp_tcp(in_port_t port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21881
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21882
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21883
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21885
	connp = ipcl_conn_create(IPCL_TCPCONN, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21886
	if (connp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21887
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21888
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21889
	tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21890
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21891
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21892
	 * Only initialize the necessary info in those structures.  Note
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21893
	 * that since INADDR_ANY is all 0, we do not need to set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21894
	 * tcp_bound_source to INADDR_ANY here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21895
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21896
	tcp->tcp_state = TCPS_BOUND;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21897
	tcp->tcp_lport = port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21898
	tcp->tcp_exclbind = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21899
	tcp->tcp_reserved_port = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21900
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21901
	/* Just for place holding... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21902
	tcp->tcp_ipversion = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21903
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21904
	return (tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21905
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21906
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21907
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21908
 * To remove a port range specified by lo_port and hi_port from the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21909
 * reserved port ranges.  This is one of the three public functions of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21910
 * the reserved port interface.  Note that a port range has to be removed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21911
 * as a whole.  Ports in a range cannot be removed individually.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21912
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21913
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21914
 *	in_port_t lo_port: the beginning port of the reserved port range to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21915
 *		be deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21916
 *	in_port_t hi_port: the ending port of the reserved port range to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21917
 *		be deleted.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21918
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21919
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21920
 *	B_TRUE if the deletion is successful, B_FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21921
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21922
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21923
tcp_reserved_port_del(in_port_t lo_port, in_port_t hi_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21924
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21925
	int	i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21926
	int	size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21927
	tcp_t	**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21928
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21929
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21930
	rw_enter(&tcp_reserved_port_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21931
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21932
	/* First make sure that the port ranage is indeed reserved. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21933
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21934
		if (tcp_reserved_port[i].lo_port == lo_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21935
			hi_port = tcp_reserved_port[i].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21936
			temp_tcp_array = tcp_reserved_port[i].temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21937
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21938
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21939
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21940
	if (i == tcp_reserved_port_array_size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21941
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21942
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21943
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21945
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21946
	 * Remove the range from the array.  This simple loop is possible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21947
	 * because port ranges are inserted in ascending order.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21948
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21949
	for (j = i; j < tcp_reserved_port_array_size - 1; j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21950
		tcp_reserved_port[j].lo_port = tcp_reserved_port[j+1].lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21951
		tcp_reserved_port[j].hi_port = tcp_reserved_port[j+1].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21952
		tcp_reserved_port[j].temp_tcp_array =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21953
		    tcp_reserved_port[j+1].temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21954
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21955
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21956
	/* Remove all the temporary tcp structures. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21957
	size = hi_port - lo_port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21958
	while (size > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21959
		tcp = temp_tcp_array[size - 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21960
		ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21961
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21962
		CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21963
		size--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21964
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21965
	kmem_free(temp_tcp_array, (hi_port - lo_port + 1) * sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21966
	tcp_reserved_port_array_size--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21967
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21968
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21969
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21970
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21971
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21972
 * Macro to remove temporary tcp structure from the bind hash list.  The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21973
 * first parameter is the list of tcp to be removed.  The second parameter
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21974
 * is the number of tcps in the array.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21975
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21976
#define	TCP_TMP_TCP_REMOVE(tcp_array, num) \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21977
{ \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21978
	while ((num) > 0) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21979
		tcp_t *tcp = (tcp_array)[(num) - 1]; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21980
		tf_t *tbf; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21981
		tcp_t *tcpnext; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21982
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(tcp->tcp_lport)]; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21983
		mutex_enter(&tbf->tf_lock); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21984
		tcpnext = tcp->tcp_bind_hash; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21985
		if (tcpnext) { \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21986
			tcpnext->tcp_ptpbhn = \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21987
				tcp->tcp_ptpbhn; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21988
		} \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21989
		*tcp->tcp_ptpbhn = tcpnext; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21990
		mutex_exit(&tbf->tf_lock); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21991
		kmem_free(tcp, sizeof (tcp_t)); \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21992
		(tcp_array)[(num) - 1] = NULL; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21993
		(num)--; \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21994
	} \
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21995
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21996
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21997
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21998
 * The public interface for other modules to call to reserve a port range
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 21999
 * in TCP.  The caller passes in how large a port range it wants.  TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22000
 * will try to find a range and return it via lo_port and hi_port.  This is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22001
 * used by NCA's nca_conn_init.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22002
 * NCA can only be used in the global zone so this only affects the global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22003
 * zone's ports.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22004
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22005
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22006
 *	int size: the size of the port range to be reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22007
 *	in_port_t *lo_port (referenced): returns the beginning port of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22008
 *		reserved port range added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22009
 *	in_port_t *hi_port (referenced): returns the ending port of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22010
 *		reserved port range added.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22011
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22012
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22013
 *	B_TRUE if the port reservation is successful, B_FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22014
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22015
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22016
tcp_reserved_port_add(int size, in_port_t *lo_port, in_port_t *hi_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22017
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22018
	tcp_t		*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22019
	tcp_t		*tmp_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22020
	tcp_t		**temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22021
	tf_t		*tbf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22022
	in_port_t	net_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22023
	in_port_t	port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22024
	int32_t		cur_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22025
	int		i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22026
	boolean_t	used;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22027
	tcp_rport_t 	tmp_ports[TCP_RESERVED_PORTS_ARRAY_MAX_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22028
	zoneid_t	zoneid = GLOBAL_ZONEID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22029
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22030
	/* Sanity check. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22031
	if (size <= 0 || size > TCP_RESERVED_PORTS_RANGE_MAX) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22032
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22033
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22034
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22035
	rw_enter(&tcp_reserved_port_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22036
	if (tcp_reserved_port_array_size == TCP_RESERVED_PORTS_ARRAY_MAX_SIZE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22037
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22038
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22039
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22040
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22041
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22042
	 * Find the starting port to try.  Since the port ranges are ordered
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22043
	 * in the reserved port array, we can do a simple search here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22044
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22045
	*lo_port = TCP_SMALLEST_RESERVED_PORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22046
	*hi_port = TCP_LARGEST_RESERVED_PORT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22047
	for (i = 0; i < tcp_reserved_port_array_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22048
	    *lo_port = tcp_reserved_port[i].hi_port + 1, i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22049
		if (tcp_reserved_port[i].lo_port - *lo_port >= size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22050
			*hi_port = tcp_reserved_port[i].lo_port - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22051
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22052
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22053
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22054
	/* No available port range. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22055
	if (i == tcp_reserved_port_array_size && *hi_port - *lo_port < size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22056
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22057
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22058
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22059
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22060
	temp_tcp_array = kmem_zalloc(size * sizeof (tcp_t *), KM_NOSLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22061
	if (temp_tcp_array == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22062
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22063
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22064
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22066
	/* Go thru the port range to see if some ports are already bound. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22067
	for (port = *lo_port, cur_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22068
	    cur_size < size && port <= *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22069
	    cur_size++, port++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22070
		used = B_FALSE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22071
		net_port = htons(port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22072
		tbf = &tcp_bind_fanout[TCP_BIND_HASH(net_port)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22073
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22074
		for (tcp = tbf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22075
		    tcp = tcp->tcp_bind_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22076
			if (zoneid == tcp->tcp_connp->conn_zoneid &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22077
			    net_port == tcp->tcp_lport) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22078
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22079
				 * A port is already bound.  Search again
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22080
				 * starting from port + 1.  Release all
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22081
				 * temporary tcps.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22082
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22083
				mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22084
				TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22085
				*lo_port = port + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22086
				cur_size = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22087
				used = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22088
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22089
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22090
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22091
		if (!used) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22092
			if ((tmp_tcp = tcp_alloc_temp_tcp(net_port)) == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22093
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22094
				 * Allocation failure.  Just fail the request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22095
				 * Need to remove all those temporary tcp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22096
				 * structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22097
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22098
				mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22099
				TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22100
				rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22101
				kmem_free(temp_tcp_array,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22102
				    (hi_port - lo_port + 1) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22103
				    sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22104
				return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22105
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22106
			temp_tcp_array[cur_size] = tmp_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22107
			tcp_bind_hash_insert(tbf, tmp_tcp, B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22108
			mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22109
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22110
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22112
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22113
	 * The current range is not large enough.  We can actually do another
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22114
	 * search if this search is done between 2 reserved port ranges.  But
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22115
	 * for first release, we just stop here and return saying that no port
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22116
	 * range is available.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22117
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22118
	if (cur_size < size) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22119
		TCP_TMP_TCP_REMOVE(temp_tcp_array, cur_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22120
		rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22121
		kmem_free(temp_tcp_array, size * sizeof (tcp_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22122
		return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22123
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22124
	*hi_port = port - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22125
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22126
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22127
	 * Insert range into array in ascending order.  Since this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22128
	 * must not be called often, we choose to use the simplest method.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22129
	 * The above array should not consume excessive stack space as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22130
	 * the size must be very small.  If in future releases, we find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22131
	 * that we should provide more reserved port ranges, this function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22132
	 * has to be modified to be more efficient.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22133
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22134
	if (tcp_reserved_port_array_size == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22135
		tcp_reserved_port[0].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22136
		tcp_reserved_port[0].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22137
		tcp_reserved_port[0].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22138
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22139
		for (i = 0, j = 0; i < tcp_reserved_port_array_size; i++, j++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22140
			if (*lo_port < tcp_reserved_port[i].lo_port && i == j) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22141
				tmp_ports[j].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22142
				tmp_ports[j].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22143
				tmp_ports[j].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22144
				j++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22145
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22146
			tmp_ports[j].lo_port = tcp_reserved_port[i].lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22147
			tmp_ports[j].hi_port = tcp_reserved_port[i].hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22148
			tmp_ports[j].temp_tcp_array =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22149
			    tcp_reserved_port[i].temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22150
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22151
		if (j == i) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22152
			tmp_ports[j].lo_port = *lo_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22153
			tmp_ports[j].hi_port = *hi_port;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22154
			tmp_ports[j].temp_tcp_array = temp_tcp_array;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22155
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22156
		bcopy(tmp_ports, tcp_reserved_port, sizeof (tmp_ports));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22157
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22158
	tcp_reserved_port_array_size++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22159
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22160
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22161
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22162
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22163
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22164
 * Check to see if a port is in any reserved port range.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22165
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22166
 * Params:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22167
 *	in_port_t port: the port to be verified.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22168
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22169
 * Return:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22170
 *	B_TRUE is the port is inside a reserved port range, B_FALSE otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22171
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22172
boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22173
tcp_reserved_port_check(in_port_t port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22174
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22175
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22177
	rw_enter(&tcp_reserved_port_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22178
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22179
		if (port >= tcp_reserved_port[i].lo_port ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22180
		    port <= tcp_reserved_port[i].hi_port) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22181
			rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22182
			return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22183
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22184
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22185
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22186
	return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22187
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22188
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22189
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22190
 * To list all reserved port ranges.  This is the function to handle
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22191
 * ndd tcp_reserved_port_list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22192
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22193
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22194
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22195
tcp_reserved_port_list(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22196
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22197
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22199
	rw_enter(&tcp_reserved_port_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22200
	if (tcp_reserved_port_array_size > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22201
		(void) mi_mpprintf(mp, "The following ports are reserved:");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22202
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22203
		(void) mi_mpprintf(mp, "No port is reserved.");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22204
	for (i = 0; i < tcp_reserved_port_array_size; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22205
		(void) mi_mpprintf(mp, "%d-%d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22206
		    tcp_reserved_port[i].lo_port, tcp_reserved_port[i].hi_port);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22207
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22208
	rw_exit(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22209
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22210
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22212
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22213
 * Hash list insertion routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22214
 * Inserts entries with the ones bound to a specific IP address first
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22215
 * followed by those bound to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22216
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22217
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22218
tcp_bind_hash_insert(tf_t *tbf, tcp_t *tcp, int caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22219
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22220
	tcp_t	**tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22221
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22223
	if (tcp->tcp_ptpbhn != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22224
		ASSERT(!caller_holds_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22225
		tcp_bind_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22226
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22227
	tcpp = &tbf->tf_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22228
	if (!caller_holds_lock) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22229
		mutex_enter(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22230
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22231
		ASSERT(MUTEX_HELD(&tbf->tf_lock));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22232
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22233
	tcpnext = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22234
	if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22235
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22236
		 * If the new tcp bound to the INADDR_ANY address
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22237
		 * and the first one in the list is not bound to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22238
		 * INADDR_ANY we skip all entries until we find the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22239
		 * first one bound to INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22240
		 * This makes sure that applications binding to a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22241
		 * specific address get preference over those binding to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22242
		 * INADDR_ANY.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22243
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22244
		if (V6_OR_V4_INADDR_ANY(tcp->tcp_bound_source_v6) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22245
		    !V6_OR_V4_INADDR_ANY(tcpnext->tcp_bound_source_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22246
			while ((tcpnext = tcpp[0]) != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22247
			    !V6_OR_V4_INADDR_ANY(tcpnext->tcp_bound_source_v6))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22248
				tcpp = &(tcpnext->tcp_bind_hash);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22249
			if (tcpnext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22250
				tcpnext->tcp_ptpbhn = &tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22251
		} else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22252
			tcpnext->tcp_ptpbhn = &tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22253
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22254
	tcp->tcp_bind_hash = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22255
	tcp->tcp_ptpbhn = tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22256
	tcpp[0] = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22257
	if (!caller_holds_lock)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22258
		mutex_exit(&tbf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22259
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22261
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22262
 * Hash list removal routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22263
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22264
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22265
tcp_bind_hash_remove(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22266
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22267
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22268
	kmutex_t *lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22270
	if (tcp->tcp_ptpbhn == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22271
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22274
	 * Extract the lock pointer in case there are concurrent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22275
	 * hash_remove's for this instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22276
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22277
	ASSERT(tcp->tcp_lport != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22278
	lockp = &tcp_bind_fanout[TCP_BIND_HASH(tcp->tcp_lport)].tf_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22280
	ASSERT(lockp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22281
	mutex_enter(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22282
	if (tcp->tcp_ptpbhn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22283
		tcpnext = tcp->tcp_bind_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22284
		if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22285
			tcpnext->tcp_ptpbhn = tcp->tcp_ptpbhn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22286
			tcp->tcp_bind_hash = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22287
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22288
		*tcp->tcp_ptpbhn = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22289
		tcp->tcp_ptpbhn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22290
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22291
	mutex_exit(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22292
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22293
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22294
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22295
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22296
 * Hash list lookup routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22297
 * Returns with a CONN_INC_REF tcp structure. Caller must do a CONN_DEC_REF.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22298
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22299
static tcp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22300
tcp_acceptor_hash_lookup(t_uscalar_t id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22301
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22302
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22303
	tcp_t	*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22304
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22305
	tf = &tcp_acceptor_fanout[TCP_ACCEPTOR_HASH(id)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22306
	mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22307
	for (tcp = tf->tf_tcp; tcp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22308
	    tcp = tcp->tcp_acceptor_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22309
		if (tcp->tcp_acceptor_id == id) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22310
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22311
			mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22312
			return (tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22313
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22314
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22315
	mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22316
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22317
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22319
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22320
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22321
 * Hash list insertion routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22322
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22323
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22324
tcp_acceptor_hash_insert(t_uscalar_t id, tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22325
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22326
	tf_t	*tf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22327
	tcp_t	**tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22328
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22330
	tf = &tcp_acceptor_fanout[TCP_ACCEPTOR_HASH(id)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22332
	if (tcp->tcp_ptpahn != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22333
		tcp_acceptor_hash_remove(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22334
	tcpp = &tf->tf_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22335
	mutex_enter(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22336
	tcpnext = tcpp[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22337
	if (tcpnext)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22338
		tcpnext->tcp_ptpahn = &tcp->tcp_acceptor_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22339
	tcp->tcp_acceptor_hash = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22340
	tcp->tcp_ptpahn = tcpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22341
	tcpp[0] = tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22342
	tcp->tcp_acceptor_lockp = &tf->tf_lock;	/* For tcp_*_hash_remove */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22343
	mutex_exit(&tf->tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22344
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22345
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22346
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22347
 * Hash list removal routine for tcp_t structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22348
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22349
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22350
tcp_acceptor_hash_remove(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22351
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22352
	tcp_t	*tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22353
	kmutex_t *lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22355
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22356
	 * Extract the lock pointer in case there are concurrent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22357
	 * hash_remove's for this instance.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22358
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22359
	lockp = tcp->tcp_acceptor_lockp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22361
	if (tcp->tcp_ptpahn == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22362
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22364
	ASSERT(lockp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22365
	mutex_enter(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22366
	if (tcp->tcp_ptpahn) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22367
		tcpnext = tcp->tcp_acceptor_hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22368
		if (tcpnext) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22369
			tcpnext->tcp_ptpahn = tcp->tcp_ptpahn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22370
			tcp->tcp_acceptor_hash = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22371
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22372
		*tcp->tcp_ptpahn = tcpnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22373
		tcp->tcp_ptpahn = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22374
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22375
	mutex_exit(lockp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22376
	tcp->tcp_acceptor_lockp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22377
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22378
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22379
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22380
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22381
tcp_host_param_setvalue(queue_t *q, mblk_t *mp, char *value, caddr_t cp, int af)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22382
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22383
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22384
	int retval;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22385
	char *end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22387
	tcp_hsp_t *hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22388
	tcp_hsp_t *hspprev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22390
	ipaddr_t addr = 0;		/* Address we're looking for */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22391
	in6_addr_t v6addr;		/* Address we're looking for */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22392
	uint32_t hash;			/* Hash of that address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22394
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22395
	 * If the following variables are still zero after parsing the input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22396
	 * string, the user didn't specify them and we don't change them in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22397
	 * the HSP.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22398
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22399
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22400
	ipaddr_t mask = 0;		/* Subnet mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22401
	in6_addr_t v6mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22402
	long sendspace = 0;		/* Send buffer size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22403
	long recvspace = 0;		/* Receive buffer size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22404
	long timestamp = 0;	/* Originate TCP TSTAMP option, 1 = yes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22405
	boolean_t delete = B_FALSE;	/* User asked to delete this HSP */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22406
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22407
	rw_enter(&tcp_hsp_lock, RW_WRITER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22409
	/* Parse and validate address */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22410
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22411
		retval = inet_pton(af, value, &addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22412
		if (retval == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22413
			IN6_IPADDR_TO_V4MAPPED(addr, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22414
	} else if (af == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22415
		retval = inet_pton(af, value, &v6addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22416
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22417
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22418
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22419
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22420
	if (retval == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22421
		error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22422
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22423
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22424
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22425
	while ((*value) && *value != ' ')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22426
		value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22428
	/* Parse individual keywords, set variables if found */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22429
	while (*value) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22430
		/* Skip leading blanks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22431
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22432
		while (*value == ' ' || *value == '\t')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22433
			value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22434
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22435
		/* If at end of string, we're done */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22437
		if (!*value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22438
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22439
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22440
		/* We have a word, figure out what it is */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22441
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22442
		if (strncmp("mask", value, 4) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22443
			value += 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22444
			while (*value == ' ' || *value == '\t')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22445
				value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22446
			/* Parse subnet mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22447
			if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22448
				retval = inet_pton(af, value, &mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22449
				if (retval == 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22450
					V4MASK_TO_V6(mask, v6mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22451
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22452
			} else if (af == AF_INET6) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22453
				retval = inet_pton(af, value, &v6mask);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22454
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22455
			if (retval != 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22456
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22457
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22458
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22459
			while ((*value) && *value != ' ')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22460
				value++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22461
		} else if (strncmp("sendspace", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22462
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22463
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22464
			if (ddi_strtol(value, &end, 0, &sendspace) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22465
			    sendspace < TCP_XMIT_HIWATER ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22466
			    sendspace >= (1L<<30)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22467
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22468
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22469
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22470
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22471
		} else if (strncmp("recvspace", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22472
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22473
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22474
			if (ddi_strtol(value, &end, 0, &recvspace) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22475
			    recvspace < TCP_RECV_HIWATER ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22476
			    recvspace >= (1L<<30)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22477
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22478
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22479
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22480
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22481
		} else if (strncmp("timestamp", value, 9) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22482
			value += 9;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22483
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22484
			if (ddi_strtol(value, &end, 0, &timestamp) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22485
			    timestamp < 0 || timestamp > 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22486
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22487
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22488
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22490
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22491
			 * We increment timestamp so we know it's been set;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22492
			 * this is undone when we put it in the HSP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22493
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22494
			timestamp++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22495
			value = end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22496
		} else if (strncmp("delete", value, 6) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22497
			value += 6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22498
			delete = B_TRUE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22499
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22500
			error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22501
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22502
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22503
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22504
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22505
	/* Hash address for lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22507
	hash = TCP_HSP_HASH(addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22509
	if (delete) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22510
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22511
		 * Note that deletes don't return an error if the thing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22512
		 * we're trying to delete isn't there.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22513
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22514
		if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22515
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22516
		hsp = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22517
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22518
		if (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22519
			if (IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22520
			    &v6addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22521
				tcp_hsp_hash[hash] = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22522
				mi_free((char *)hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22523
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22524
				hspprev = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22525
				while ((hsp = hsp->tcp_hsp_next) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22526
					if (IN6_ARE_ADDR_EQUAL(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22527
					    &hsp->tcp_hsp_addr_v6, &v6addr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22528
						hspprev->tcp_hsp_next =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22529
						    hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22530
						mi_free((char *)hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22531
						break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22532
					}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22533
					hspprev = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22534
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22535
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22536
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22537
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22538
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22539
		 * We're adding/modifying an HSP.  If we haven't already done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22540
		 * so, allocate the hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22541
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22542
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22543
		if (!tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22544
			tcp_hsp_hash = (tcp_hsp_t **)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22545
			    mi_zalloc(sizeof (tcp_hsp_t *) * TCP_HSP_HASH_SIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22546
			if (!tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22547
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22548
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22549
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22550
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22551
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22552
		/* Get head of hash chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22553
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22554
		hsp = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22556
		/* Try to find pre-existing hsp on hash chain */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22557
		/* Doesn't handle CIDR prefixes. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22558
		while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22559
			if (IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6, &v6addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22560
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22561
			hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22562
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22564
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22565
		 * If we didn't, create one with default values and put it
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22566
		 * at head of hash chain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22567
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22568
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22569
		if (!hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22570
			hsp = (tcp_hsp_t *)mi_zalloc(sizeof (tcp_hsp_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22571
			if (!hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22572
				error = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22573
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22574
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22575
			hsp->tcp_hsp_next = tcp_hsp_hash[hash];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22576
			tcp_hsp_hash[hash] = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22577
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22579
		/* Set values that the user asked us to change */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22580
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22581
		hsp->tcp_hsp_addr_v6 = v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22582
		if (IN6_IS_ADDR_V4MAPPED(&v6addr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22583
			hsp->tcp_hsp_vers = IPV4_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22584
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22585
			hsp->tcp_hsp_vers = IPV6_VERSION;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22586
		hsp->tcp_hsp_subnet_v6 = v6mask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22587
		if (sendspace > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22588
			hsp->tcp_hsp_sendspace = sendspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22589
		if (recvspace > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22590
			hsp->tcp_hsp_recvspace = recvspace;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22591
		if (timestamp > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22592
			hsp->tcp_hsp_tstamp = timestamp - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22595
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22596
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22597
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22598
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22600
/* Set callback routine passed to nd_load by tcp_param_register. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22601
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22602
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22603
tcp_host_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22604
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22605
	return (tcp_host_param_setvalue(q, mp, value, cp, AF_INET));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22606
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22607
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22608
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22609
tcp_host_param_set_ipv6(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22610
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22611
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22612
	return (tcp_host_param_setvalue(q, mp, value, cp, AF_INET6));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22613
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22615
/* TCP host parameters report triggered via the Named Dispatch mechanism. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22616
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22617
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22618
tcp_host_param_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22619
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22620
	tcp_hsp_t *hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22621
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22622
	char addrbuf[INET6_ADDRSTRLEN], subnetbuf[INET6_ADDRSTRLEN];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22624
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22625
	(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22626
	    "Hash HSP     " MI_COL_HDRPAD_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22627
	    "Address         Subnet Mask     Send       Receive    TStamp");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22628
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22629
		for (i = 0; i < TCP_HSP_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22630
			hsp = tcp_hsp_hash[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22631
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22632
				if (hsp->tcp_hsp_vers == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22633
					(void) inet_ntop(AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22634
					    &hsp->tcp_hsp_addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22635
					    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22636
					(void) inet_ntop(AF_INET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22637
					    &hsp->tcp_hsp_subnet,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22638
					    subnetbuf, sizeof (subnetbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22639
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22640
					(void) inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22641
					    &hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22642
					    addrbuf, sizeof (addrbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22643
					(void) inet_ntop(AF_INET6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22644
					    &hsp->tcp_hsp_subnet_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22645
					    subnetbuf, sizeof (subnetbuf));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22646
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22647
				(void) mi_mpprintf(mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22648
				    " %03d " MI_COL_PTRFMT_STR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22649
				    "%s %s %010d %010d      %d",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22650
				    i,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22651
				    (void *)hsp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22652
				    addrbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22653
				    subnetbuf,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22654
				    hsp->tcp_hsp_sendspace,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22655
				    hsp->tcp_hsp_recvspace,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22656
				    hsp->tcp_hsp_tstamp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22657
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22658
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22659
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22660
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22661
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22662
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22663
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22664
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22665
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22666
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22667
/* Data for fast netmask macro used by tcp_hsp_lookup */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22668
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22669
static ipaddr_t netmasks[] = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22670
	IN_CLASSA_NET, IN_CLASSA_NET, IN_CLASSB_NET,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22671
	IN_CLASSC_NET | IN_CLASSD_NET  /* Class C,D,E */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22672
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22674
#define	netmask(addr) (netmasks[(ipaddr_t)(addr) >> 30])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22675
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22676
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22677
 * XXX This routine should go away and instead we should use the metrics
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22678
 * associated with the routes to determine the default sndspace and rcvspace.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22679
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22680
static tcp_hsp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22681
tcp_hsp_lookup(ipaddr_t addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22682
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22683
	tcp_hsp_t *hsp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22684
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22685
	/* Quick check without acquiring the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22686
	if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22687
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22688
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22689
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22690
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22691
	/* This routine finds the best-matching HSP for address addr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22692
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22693
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22694
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22695
		ipaddr_t srchaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22696
		tcp_hsp_t *hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22697
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22698
		/* We do three passes: host, network, and subnet. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22700
		srchaddr = addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22701
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22702
		for (i = 1; i <= 3; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22703
			/* Look for exact match on srchaddr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22704
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22705
			hsp = tcp_hsp_hash[TCP_HSP_HASH(srchaddr)];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22706
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22707
				if (hsp->tcp_hsp_vers == IPV4_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22708
				    hsp->tcp_hsp_addr == srchaddr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22709
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22710
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22711
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22712
			ASSERT(hsp == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22713
			    hsp->tcp_hsp_vers == IPV4_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22714
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22715
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22716
			 * If this is the first pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22717
			 *   If we found a match, great, return it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22718
			 *   If not, search for the network on the second pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22719
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22721
			if (i == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22722
				if (hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22723
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22724
				else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22725
				{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22726
					srchaddr = addr & netmask(addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22727
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22728
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22729
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22730
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22731
			 * If this is the second pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22732
			 *   If we found a match, but there's a subnet mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22733
			 *    save the match but try again using the subnet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22734
			 *    mask on the third pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22735
			 *   Otherwise, return whatever we found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22736
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22737
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22738
			if (i == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22739
				if (hsp && hsp->tcp_hsp_subnet) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22740
					hsp_net = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22741
					srchaddr = addr & hsp->tcp_hsp_subnet;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22742
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22743
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22744
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22745
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22746
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22747
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22748
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22749
			 * This must be the third pass.  If we didn't find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22750
			 * anything, return the saved network HSP instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22751
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22752
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22753
			if (!hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22754
				hsp = hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22755
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22756
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22758
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22759
	return (hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22760
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22762
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22763
 * XXX Equally broken as the IPv4 routine. Doesn't handle longest
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22764
 * match lookup.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22765
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22766
static tcp_hsp_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22767
tcp_hsp_lookup_ipv6(in6_addr_t *v6addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22768
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22769
	tcp_hsp_t *hsp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22771
	/* Quick check without acquiring the lock. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22772
	if (tcp_hsp_hash == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22773
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22774
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22775
	rw_enter(&tcp_hsp_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22776
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22777
	/* This routine finds the best-matching HSP for address addr. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22778
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22779
	if (tcp_hsp_hash) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22780
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22781
		in6_addr_t v6srchaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22782
		tcp_hsp_t *hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22784
		/* We do three passes: host, network, and subnet. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22785
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22786
		v6srchaddr = *v6addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22787
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22788
		for (i = 1; i <= 3; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22789
			/* Look for exact match on srchaddr */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22791
			hsp = tcp_hsp_hash[TCP_HSP_HASH(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22792
			    V4_PART_OF_V6(v6srchaddr))];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22793
			while (hsp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22794
				if (hsp->tcp_hsp_vers == IPV6_VERSION &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22795
				    IN6_ARE_ADDR_EQUAL(&hsp->tcp_hsp_addr_v6,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22796
				    &v6srchaddr))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22797
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22798
				hsp = hsp->tcp_hsp_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22799
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22801
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22802
			 * If this is the first pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22803
			 *   If we found a match, great, return it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22804
			 *   If not, search for the network on the second pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22805
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22806
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22807
			if (i == 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22808
				if (hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22809
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22810
				else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22811
					/* Assume a 64 bit mask */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22812
					v6srchaddr.s6_addr32[0] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22813
					    v6addr->s6_addr32[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22814
					v6srchaddr.s6_addr32[1] =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22815
					    v6addr->s6_addr32[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22816
					v6srchaddr.s6_addr32[2] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22817
					v6srchaddr.s6_addr32[3] = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22818
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22819
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22820
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22821
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22822
			 * If this is the second pass:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22823
			 *   If we found a match, but there's a subnet mask,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22824
			 *    save the match but try again using the subnet
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22825
			 *    mask on the third pass.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22826
			 *   Otherwise, return whatever we found.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22827
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22828
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22829
			if (i == 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22830
				ASSERT(hsp == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22831
				    hsp->tcp_hsp_vers == IPV6_VERSION);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22832
				if (hsp &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22833
				    !IN6_IS_ADDR_UNSPECIFIED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22834
				    &hsp->tcp_hsp_subnet_v6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22835
					hsp_net = hsp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22836
					V6_MASK_COPY(*v6addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22837
					    hsp->tcp_hsp_subnet_v6, v6srchaddr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22838
					continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22839
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22840
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22841
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22842
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22844
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22845
			 * This must be the third pass.  If we didn't find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22846
			 * anything, return the saved network HSP instead.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22847
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22848
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22849
			if (!hsp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22850
				hsp = hsp_net;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22851
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22852
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22853
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22854
	rw_exit(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22855
	return (hsp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22856
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22857
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22858
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22859
 * Type three generator adapted from the random() function in 4.4 BSD:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22860
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22862
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22863
 * Copyright (c) 1983, 1993
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22864
 *	The Regents of the University of California.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22865
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22866
 * Redistribution and use in source and binary forms, with or without
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22867
 * modification, are permitted provided that the following conditions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22868
 * are met:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22869
 * 1. Redistributions of source code must retain the above copyright
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22870
 *    notice, this list of conditions and the following disclaimer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22871
 * 2. Redistributions in binary form must reproduce the above copyright
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22872
 *    notice, this list of conditions and the following disclaimer in the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22873
 *    documentation and/or other materials provided with the distribution.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22874
 * 3. All advertising materials mentioning features or use of this software
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22875
 *    must display the following acknowledgement:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22876
 *	This product includes software developed by the University of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22877
 *	California, Berkeley and its contributors.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22878
 * 4. Neither the name of the University nor the names of its contributors
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22879
 *    may be used to endorse or promote products derived from this software
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22880
 *    without specific prior written permission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22881
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22882
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22883
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22884
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22885
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22886
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22887
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22888
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22889
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22890
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22891
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22892
 * SUCH DAMAGE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22893
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22894
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22895
/* Type 3 -- x**31 + x**3 + 1 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22896
#define	DEG_3		31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22897
#define	SEP_3		3
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22898
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22899
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22900
/* Protected by tcp_random_lock */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22901
static int tcp_randtbl[DEG_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22902
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22903
static int *tcp_random_fptr = &tcp_randtbl[SEP_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22904
static int *tcp_random_rptr = &tcp_randtbl[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22905
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22906
static int *tcp_random_state = &tcp_randtbl[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22907
static int *tcp_random_end_ptr = &tcp_randtbl[DEG_3 + 1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22908
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22909
kmutex_t tcp_random_lock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22910
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22911
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22912
tcp_random_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22913
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22914
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22915
	hrtime_t hrt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22916
	time_t wallclock;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22917
	uint64_t result;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22918
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22919
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22920
	 * Use high-res timer and current time for seed.  Gethrtime() returns
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22921
	 * a longlong, which may contain resolution down to nanoseconds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22922
	 * The current time will either be a 32-bit or a 64-bit quantity.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22923
	 * XOR the two together in a 64-bit result variable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22924
	 * Convert the result to a 32-bit value by multiplying the high-order
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22925
	 * 32-bits by the low-order 32-bits.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22926
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22927
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22928
	hrt = gethrtime();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22929
	(void) drv_getparm(TIME, &wallclock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22930
	result = (uint64_t)wallclock ^ (uint64_t)hrt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22931
	mutex_enter(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22932
	tcp_random_state[0] = ((result >> 32) & 0xffffffff) *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22933
	    (result & 0xffffffff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22934
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22935
	for (i = 1; i < DEG_3; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22936
		tcp_random_state[i] = 1103515245 * tcp_random_state[i - 1]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22937
			+ 12345;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22938
	tcp_random_fptr = &tcp_random_state[SEP_3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22939
	tcp_random_rptr = &tcp_random_state[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22940
	mutex_exit(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22941
	for (i = 0; i < 10 * DEG_3; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22942
		(void) tcp_random();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22943
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22944
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22945
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22946
 * tcp_random: Return a random number in the range [1 - (128K + 1)].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22947
 * This range is selected to be approximately centered on TCP_ISS / 2,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22948
 * and easy to compute. We get this value by generating a 32-bit random
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22949
 * number, selecting out the high-order 17 bits, and then adding one so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22950
 * that we never return zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22951
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22952
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22953
tcp_random(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22954
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22955
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22956
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22957
	mutex_enter(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22958
	*tcp_random_fptr += *tcp_random_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22960
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22961
	 * The high-order bits are more random than the low-order bits,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22962
	 * so we select out the high-order 17 bits and add one so that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22963
	 * we never return zero.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22964
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22965
	i = ((*tcp_random_fptr >> 15) & 0x1ffff) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22966
	if (++tcp_random_fptr >= tcp_random_end_ptr) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22967
		tcp_random_fptr = tcp_random_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22968
		++tcp_random_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22969
	} else if (++tcp_random_rptr >= tcp_random_end_ptr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22970
		tcp_random_rptr = tcp_random_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22971
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22972
	mutex_exit(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22973
	return (i);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22974
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22975
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22976
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22977
 * XXX This will go away when TPI is extended to send
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22978
 * info reqs to sockfs/timod .....
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22979
 * Given a queue, set the max packet size for the write
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22980
 * side of the queue below stream head.  This value is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22981
 * cached on the stream head.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22982
 * Returns 1 on success, 0 otherwise.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22983
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22984
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22985
setmaxps(queue_t *q, int maxpsz)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22986
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22987
	struct stdata	*stp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22988
	queue_t		*wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22989
	stp = STREAM(q);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22990
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22991
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22992
	 * At this point change of a queue parameter is not allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22993
	 * when a multiplexor is sitting on top.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22994
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22995
	if (stp->sd_flag & STPLEX)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22996
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22997
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22998
	claimstr(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 22999
	wq = stp->sd_wrq->q_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23000
	ASSERT(wq != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23001
	(void) strqset(wq, QMAXPSZ, 0, maxpsz);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23002
	releasestr(stp->sd_wrq);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23003
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23004
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23005
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23006
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23007
tcp_conprim_opt_process(tcp_t *tcp, mblk_t *mp, int *do_disconnectp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23008
    int *t_errorp, int *sys_errorp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23009
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23010
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23011
	int is_absreq_failure;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23012
	t_scalar_t *opt_lenp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23013
	t_scalar_t opt_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23014
	int prim_type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23015
	struct T_conn_req *tcreqp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23016
	struct T_conn_res *tcresp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23017
	cred_t *cr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23018
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23019
	cr = DB_CREDDEF(mp, tcp->tcp_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23020
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23021
	prim_type = ((union T_primitives *)mp->b_rptr)->type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23022
	ASSERT(prim_type == T_CONN_REQ || prim_type == O_T_CONN_RES ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23023
	    prim_type == T_CONN_RES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23024
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23025
	switch (prim_type) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23026
	case T_CONN_REQ:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23027
		tcreqp = (struct T_conn_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23028
		opt_offset = tcreqp->OPT_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23029
		opt_lenp = (t_scalar_t *)&tcreqp->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23030
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23031
	case O_T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23032
	case T_CONN_RES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23033
		tcresp = (struct T_conn_res *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23034
		opt_offset = tcresp->OPT_offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23035
		opt_lenp = (t_scalar_t *)&tcresp->OPT_length;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23036
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23037
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23038
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23039
	*t_errorp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23040
	*sys_errorp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23041
	*do_disconnectp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23042
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23043
	error = tpi_optcom_buf(tcp->tcp_wq, mp, opt_lenp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23044
	    opt_offset, cr, &tcp_opt_obj,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23045
	    NULL, &is_absreq_failure);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23046
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23047
	switch (error) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23048
	case  0:		/* no error */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23049
		ASSERT(is_absreq_failure == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23050
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23051
	case ENOPROTOOPT:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23052
		*t_errorp = TBADOPT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23053
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23054
	case EACCES:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23055
		*t_errorp = TACCES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23056
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23057
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23058
		*t_errorp = TSYSERR; *sys_errorp = error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23059
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23060
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23061
	if (is_absreq_failure != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23062
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23063
		 * The connection request should get the local ack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23064
		 * T_OK_ACK and then a T_DISCON_IND.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23065
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23066
		*do_disconnectp = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23067
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23068
	return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23069
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23070
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23071
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23072
 * Split this function out so that if the secret changes, I'm okay.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23073
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23074
 * Initialize the tcp_iss_cookie and tcp_iss_key.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23075
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23076
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23077
#define	PASSWD_SIZE 16  /* MUST be multiple of 4 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23078
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23079
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23080
tcp_iss_key_init(uint8_t *phrase, int len)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23081
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23082
	struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23083
		int32_t current_time;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23084
		uint32_t randnum;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23085
		uint16_t pad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23086
		uint8_t ether[6];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23087
		uint8_t passwd[PASSWD_SIZE];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23088
	} tcp_iss_cookie;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23089
	time_t t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23090
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23091
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23092
	 * Start with the current absolute time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23093
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23094
	(void) drv_getparm(TIME, &t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23095
	tcp_iss_cookie.current_time = t;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23096
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23097
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23098
	 * XXX - Need a more random number per RFC 1750, not this crap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23099
	 * OTOH, if what follows is pretty random, then I'm in better shape.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23100
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23101
	tcp_iss_cookie.randnum = (uint32_t)(gethrtime() + tcp_random());
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23102
	tcp_iss_cookie.pad = 0x365c;  /* Picked from HMAC pad values. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23103
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23104
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23105
	 * The cpu_type_info is pretty non-random.  Ugggh.  It does serve
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23106
	 * as a good template.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23107
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23108
	bcopy(&cpu_list->cpu_type_info, &tcp_iss_cookie.passwd,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23109
	    min(PASSWD_SIZE, sizeof (cpu_list->cpu_type_info)));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23110
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23111
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23112
	 * The pass-phrase.  Normally this is supplied by user-called NDD.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23113
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23114
	bcopy(phrase, &tcp_iss_cookie.passwd, min(PASSWD_SIZE, len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23116
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23117
	 * See 4010593 if this section becomes a problem again,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23118
	 * but the local ethernet address is useful here.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23119
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23120
	(void) localetheraddr(NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23121
	    (struct ether_addr *)&tcp_iss_cookie.ether);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23122
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23123
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23124
	 * Hash 'em all together.  The MD5Final is called per-connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23125
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23126
	mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23127
	MD5Init(&tcp_iss_key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23128
	MD5Update(&tcp_iss_key, (uchar_t *)&tcp_iss_cookie,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23129
	    sizeof (tcp_iss_cookie));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23130
	mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23131
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23132
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23133
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23134
 * Set the RFC 1948 pass phrase
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23135
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23136
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23137
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23138
tcp_1948_phrase_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23139
    cred_t *cr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23140
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23141
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23142
	 * Basically, value contains a new pass phrase.  Pass it along!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23143
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23144
	tcp_iss_key_init((uint8_t *)value, strlen(value));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23145
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23146
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23147
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23148
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23149
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23150
tcp_sack_info_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23151
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23152
	bzero(buf, sizeof (tcp_sack_info_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23153
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23154
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23156
/* ARGSUSED */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23157
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23158
tcp_iphc_constructor(void *buf, void *cdrarg, int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23159
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23160
	bzero(buf, TCP_MAX_COMBINED_HEADER_LENGTH);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23161
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23162
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23164
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23165
tcp_ddi_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23166
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23167
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23168
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23169
	/* Initialize locks */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23170
	rw_init(&tcp_hsp_lock, NULL, RW_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23171
	mutex_init(&tcp_g_q_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23172
	mutex_init(&tcp_random_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23173
	mutex_init(&tcp_iss_key_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23174
	mutex_init(&tcp_epriv_port_lock, NULL, MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23175
	rw_init(&tcp_reserved_port_lock, NULL, RW_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23176
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23177
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23178
		mutex_init(&tcp_bind_fanout[i].tf_lock, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23179
		    MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23180
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23181
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23182
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23183
		mutex_init(&tcp_acceptor_fanout[i].tf_lock, NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23184
		    MUTEX_DEFAULT, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23185
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23186
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23187
	/* TCP's IPsec code calls the packet dropper. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23188
	ip_drop_register(&tcp_dropper, "TCP IPsec policy enforcement");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23190
	if (!tcp_g_nd) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23191
		if (!tcp_param_register(tcp_param_arr, A_CNT(tcp_param_arr))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23192
			nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23193
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23194
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23196
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23197
	 * Note: To really walk the device tree you need the devinfo
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23198
	 * pointer to your device which is only available after probe/attach.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23199
	 * The following is safe only because it uses ddi_root_node()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23200
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23201
	tcp_max_optsize = optcom_max_optsize(tcp_opt_obj.odb_opt_des_arr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23202
	    tcp_opt_obj.odb_opt_arr_cnt);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23203
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23204
	tcp_timercache = kmem_cache_create("tcp_timercache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23205
	    sizeof (tcp_timer_t) + sizeof (mblk_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23206
	    NULL, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23208
	tcp_sack_info_cache = kmem_cache_create("tcp_sack_info_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23209
	    sizeof (tcp_sack_info_t), 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23210
	    tcp_sack_info_constructor, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23212
	tcp_iphc_cache = kmem_cache_create("tcp_iphc_cache",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23213
	    TCP_MAX_COMBINED_HEADER_LENGTH, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23214
	    tcp_iphc_constructor, NULL, NULL, NULL, NULL, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23216
	tcp_squeue_wput_proc = tcp_squeue_switch(tcp_squeue_wput);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23217
	tcp_squeue_close_proc = tcp_squeue_switch(tcp_squeue_close);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23219
	ip_squeue_init(tcp_squeue_add);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23221
	/* Initialize the random number generator */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23222
	tcp_random_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23224
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23225
	 * Initialize RFC 1948 secret values.  This will probably be reset once
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23226
	 * by the boot scripts.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23227
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23228
	 * Use NULL name, as the name is caught by the new lockstats.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23229
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23230
	 * Initialize with some random, non-guessable string, like the global
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23231
	 * T_INFO_ACK.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23232
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23233
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23234
	tcp_iss_key_init((uint8_t *)&tcp_g_t_info_ack,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23235
	    sizeof (tcp_g_t_info_ack));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23236
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23237
	if ((tcp_kstat = kstat_create(TCP_MOD_NAME, 0, "tcpstat",
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23238
		"net", KSTAT_TYPE_NAMED,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23239
		sizeof (tcp_statistics) / sizeof (kstat_named_t),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23240
		KSTAT_FLAG_VIRTUAL)) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23241
		tcp_kstat->ks_data = &tcp_statistics;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23242
		kstat_install(tcp_kstat);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23243
	}
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23244
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23245
	tcp_kstat_init();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23246
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23248
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23249
tcp_ddi_destroy(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23250
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23251
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23253
	nd_free(&tcp_g_nd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23254
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23255
	for (i = 0; i < A_CNT(tcp_bind_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23256
		mutex_destroy(&tcp_bind_fanout[i].tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23257
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23259
	for (i = 0; i < A_CNT(tcp_acceptor_fanout); i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23260
		mutex_destroy(&tcp_acceptor_fanout[i].tf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23261
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23262
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23263
	mutex_destroy(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23264
	rw_destroy(&tcp_hsp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23265
	mutex_destroy(&tcp_g_q_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23266
	mutex_destroy(&tcp_random_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23267
	mutex_destroy(&tcp_epriv_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23268
	rw_destroy(&tcp_reserved_port_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23270
	ip_drop_unregister(&tcp_dropper);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23272
	kmem_cache_destroy(tcp_timercache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23273
	kmem_cache_destroy(tcp_sack_info_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23274
	kmem_cache_destroy(tcp_iphc_cache);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23275
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23276
	tcp_kstat_fini();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23277
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23278
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23279
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23280
 * Generate ISS, taking into account NDD changes may happen halfway through.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23281
 * (If the iss is not zero, set it.)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23282
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23283
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23284
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23285
tcp_iss_init(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23286
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23287
	MD5_CTX context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23288
	struct { uint32_t ports; in6_addr_t src; in6_addr_t dst; } arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23289
	uint32_t answer[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23291
	tcp_iss_incr_extra += (ISS_INCR >> 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23292
	tcp->tcp_iss = tcp_iss_incr_extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23293
	switch (tcp_strong_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23294
	case 2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23295
		mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23296
		context = tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23297
		mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23298
		arg.ports = tcp->tcp_ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23299
		if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23300
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_src,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23301
			    &arg.src);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23302
			IN6_IPADDR_TO_V4MAPPED(tcp->tcp_ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23303
			    &arg.dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23304
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23305
			arg.src = tcp->tcp_ip6h->ip6_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23306
			arg.dst = tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23307
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23308
		MD5Update(&context, (uchar_t *)&arg, sizeof (arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23309
		MD5Final((uchar_t *)answer, &context);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23310
		tcp->tcp_iss += answer[0] ^ answer[1] ^ answer[2] ^ answer[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23311
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23312
		 * Now that we've hashed into a unique per-connection sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23313
		 * space, add a random increment per strong_iss == 1.  So I
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23314
		 * guess we'll have to...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23315
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23316
		/* FALLTHRU */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23317
	case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23318
		tcp->tcp_iss += (gethrtime() >> ISS_NSEC_SHT) + tcp_random();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23319
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23320
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23321
		tcp->tcp_iss += (uint32_t)gethrestime_sec() * ISS_INCR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23322
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23323
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23324
	tcp->tcp_valid_bits = TCP_ISS_VALID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23325
	tcp->tcp_fss = tcp->tcp_iss - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23326
	tcp->tcp_suna = tcp->tcp_iss;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23327
	tcp->tcp_snxt = tcp->tcp_iss + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23328
	tcp->tcp_rexmit_nxt = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23329
	tcp->tcp_csuna = tcp->tcp_snxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23330
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23331
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23332
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23333
 * Exported routine for extracting active tcp connection status.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23334
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23335
 * This is used by the Solaris Cluster Networking software to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23336
 * gather a list of connections that need to be forwarded to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23337
 * specific nodes in the cluster when configuration changes occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23338
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23339
 * The callback is invoked for each tcp_t structure. Returning
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23340
 * non-zero from the callback routine terminates the search.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23341
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23342
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23343
cl_tcp_walk_list(int (*callback)(cl_tcp_info_t *, void *), void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23344
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23345
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23346
	cl_tcp_info_t	cl_tcpi;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23347
	connf_t	*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23348
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23349
	int	i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23350
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23351
	ASSERT(callback != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23352
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23353
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23355
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23356
		connp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23357
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23358
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23359
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23360
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23361
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23362
			cl_tcpi.cl_tcpi_version = CL_TCPI_V1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23363
			cl_tcpi.cl_tcpi_ipversion = tcp->tcp_ipversion;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23364
			cl_tcpi.cl_tcpi_state = tcp->tcp_state;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23365
			cl_tcpi.cl_tcpi_lport = tcp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23366
			cl_tcpi.cl_tcpi_fport = tcp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23367
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23368
			 * The macros tcp_laddr and tcp_faddr give the IPv4
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23369
			 * addresses. They are copied implicitly below as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23370
			 * mapped addresses.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23371
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23372
			cl_tcpi.cl_tcpi_laddr_v6 = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23373
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23374
				cl_tcpi.cl_tcpi_faddr =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23375
				    tcp->tcp_ipha->ipha_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23376
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23377
				cl_tcpi.cl_tcpi_faddr_v6 =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23378
				    tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23379
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23380
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23381
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23382
			 * If the callback returns non-zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23383
			 * we terminate the traversal.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23384
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23385
			if ((*callback)(&cl_tcpi, arg) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23386
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23387
				return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23388
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23389
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23390
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23391
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23392
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23393
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23394
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23395
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23396
 * Macros used for accessing the different types of sockaddr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23397
 * structures inside a tcp_ioc_abort_conn_t.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23398
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23399
#define	TCP_AC_V4LADDR(acp) ((sin_t *)&(acp)->ac_local)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23400
#define	TCP_AC_V4RADDR(acp) ((sin_t *)&(acp)->ac_remote)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23401
#define	TCP_AC_V4LOCAL(acp) (TCP_AC_V4LADDR(acp)->sin_addr.s_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23402
#define	TCP_AC_V4REMOTE(acp) (TCP_AC_V4RADDR(acp)->sin_addr.s_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23403
#define	TCP_AC_V4LPORT(acp) (TCP_AC_V4LADDR(acp)->sin_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23404
#define	TCP_AC_V4RPORT(acp) (TCP_AC_V4RADDR(acp)->sin_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23405
#define	TCP_AC_V6LADDR(acp) ((sin6_t *)&(acp)->ac_local)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23406
#define	TCP_AC_V6RADDR(acp) ((sin6_t *)&(acp)->ac_remote)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23407
#define	TCP_AC_V6LOCAL(acp) (TCP_AC_V6LADDR(acp)->sin6_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23408
#define	TCP_AC_V6REMOTE(acp) (TCP_AC_V6RADDR(acp)->sin6_addr)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23409
#define	TCP_AC_V6LPORT(acp) (TCP_AC_V6LADDR(acp)->sin6_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23410
#define	TCP_AC_V6RPORT(acp) (TCP_AC_V6RADDR(acp)->sin6_port)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23411
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23412
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23413
 * Return the correct error code to mimic the behavior
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23414
 * of a connection reset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23415
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23416
#define	TCP_AC_GET_ERRCODE(state, err) {	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23417
		switch ((state)) {		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23418
		case TCPS_SYN_SENT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23419
		case TCPS_SYN_RCVD:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23420
			(err) = ECONNREFUSED;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23421
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23422
		case TCPS_ESTABLISHED:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23423
		case TCPS_FIN_WAIT_1:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23424
		case TCPS_FIN_WAIT_2:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23425
		case TCPS_CLOSE_WAIT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23426
			(err) = ECONNRESET;	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23427
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23428
		case TCPS_CLOSING:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23429
		case TCPS_LAST_ACK:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23430
		case TCPS_TIME_WAIT:		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23431
			(err) = 0;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23432
			break;			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23433
		default:			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23434
			(err) = ENXIO;		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23435
		}				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23436
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23437
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23438
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23439
 * Check if a tcp structure matches the info in acp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23440
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23441
#define	TCP_AC_ADDR_MATCH(acp, tcp)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23442
	(((acp)->ac_local.ss_family == AF_INET) ?		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23443
	((TCP_AC_V4LOCAL((acp)) == INADDR_ANY ||		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23444
	TCP_AC_V4LOCAL((acp)) == (tcp)->tcp_ip_src) &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23445
	(TCP_AC_V4REMOTE((acp)) == INADDR_ANY ||		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23446
	TCP_AC_V4REMOTE((acp)) == (tcp)->tcp_remote) &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23447
	(TCP_AC_V4LPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23448
	TCP_AC_V4LPORT((acp)) == (tcp)->tcp_lport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23449
	(TCP_AC_V4RPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23450
	TCP_AC_V4RPORT((acp)) == (tcp)->tcp_fport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23451
	(acp)->ac_start <= (tcp)->tcp_state &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23452
	(acp)->ac_end >= (tcp)->tcp_state) :		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23453
	((IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6LOCAL((acp))) ||	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23454
	IN6_ARE_ADDR_EQUAL(&TCP_AC_V6LOCAL((acp)),		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23455
	&(tcp)->tcp_ip_src_v6)) &&				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23456
	(IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6REMOTE((acp))) ||	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23457
	IN6_ARE_ADDR_EQUAL(&TCP_AC_V6REMOTE((acp)),		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23458
	&(tcp)->tcp_remote_v6)) &&				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23459
	(TCP_AC_V6LPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23460
	TCP_AC_V6LPORT((acp)) == (tcp)->tcp_lport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23461
	(TCP_AC_V6RPORT((acp)) == 0 ||				\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23462
	TCP_AC_V6RPORT((acp)) == (tcp)->tcp_fport) &&		\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23463
	(acp)->ac_start <= (tcp)->tcp_state &&	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23464
	(acp)->ac_end >= (tcp)->tcp_state))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23465
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23466
#define	TCP_AC_MATCH(acp, tcp)					\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23467
	(((acp)->ac_zoneid == ALL_ZONES ||			\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23468
	(acp)->ac_zoneid == tcp->tcp_connp->conn_zoneid) ?	\
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23469
	TCP_AC_ADDR_MATCH(acp, tcp) : 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23470
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23471
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23472
 * Build a message containing a tcp_ioc_abort_conn_t structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23473
 * which is filled in with information from acp and tp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23474
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23475
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23476
tcp_ioctl_abort_build_msg(tcp_ioc_abort_conn_t *acp, tcp_t *tp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23477
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23478
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23479
	tcp_ioc_abort_conn_t *tacp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23480
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23481
	mp = allocb(sizeof (uint32_t) + sizeof (*acp), BPRI_LO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23482
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23483
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23484
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23485
	mp->b_datap->db_type = M_CTL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23487
	*((uint32_t *)mp->b_rptr) = TCP_IOC_ABORT_CONN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23488
	tacp = (tcp_ioc_abort_conn_t *)((uchar_t *)mp->b_rptr +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23489
		sizeof (uint32_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23491
	tacp->ac_start = acp->ac_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23492
	tacp->ac_end = acp->ac_end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23493
	tacp->ac_zoneid = acp->ac_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23495
	if (acp->ac_local.ss_family == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23496
		tacp->ac_local.ss_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23497
		tacp->ac_remote.ss_family = AF_INET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23498
		TCP_AC_V4LOCAL(tacp) = tp->tcp_ip_src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23499
		TCP_AC_V4REMOTE(tacp) = tp->tcp_remote;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23500
		TCP_AC_V4LPORT(tacp) = tp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23501
		TCP_AC_V4RPORT(tacp) = tp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23502
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23503
		tacp->ac_local.ss_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23504
		tacp->ac_remote.ss_family = AF_INET6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23505
		TCP_AC_V6LOCAL(tacp) = tp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23506
		TCP_AC_V6REMOTE(tacp) = tp->tcp_remote_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23507
		TCP_AC_V6LPORT(tacp) = tp->tcp_lport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23508
		TCP_AC_V6RPORT(tacp) = tp->tcp_fport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23509
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23510
	mp->b_wptr = (uchar_t *)mp->b_rptr + sizeof (uint32_t) + sizeof (*acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23511
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23512
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23513
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23514
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23515
 * Print a tcp_ioc_abort_conn_t structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23516
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23517
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23518
tcp_ioctl_abort_dump(tcp_ioc_abort_conn_t *acp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23519
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23520
	char lbuf[128];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23521
	char rbuf[128];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23522
	sa_family_t af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23523
	in_port_t lport, rport;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23524
	ushort_t logflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23526
	af = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23528
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23529
		(void) inet_ntop(af, (const void *)&TCP_AC_V4LOCAL(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23530
				lbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23531
		(void) inet_ntop(af, (const void *)&TCP_AC_V4REMOTE(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23532
				rbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23533
		lport = ntohs(TCP_AC_V4LPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23534
		rport = ntohs(TCP_AC_V4RPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23535
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23536
		(void) inet_ntop(af, (const void *)&TCP_AC_V6LOCAL(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23537
				lbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23538
		(void) inet_ntop(af, (const void *)&TCP_AC_V6REMOTE(acp),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23539
				rbuf, 128);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23540
		lport = ntohs(TCP_AC_V6LPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23541
		rport = ntohs(TCP_AC_V6RPORT(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23542
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23543
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23544
	logflags = SL_TRACE | SL_NOTE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23545
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23546
	 * Don't print this message to the console if the operation was done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23547
	 * to a non-global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23548
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23549
	if (acp->ac_zoneid == GLOBAL_ZONEID || acp->ac_zoneid == ALL_ZONES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23550
		logflags |= SL_CONSOLE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23551
	(void) strlog(TCP_MOD_ID, 0, 1, logflags,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23552
		"TCP_IOC_ABORT_CONN: local = %s:%d, remote = %s:%d, "
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23553
		"start = %d, end = %d\n", lbuf, lport, rbuf, rport,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23554
		acp->ac_start, acp->ac_end);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23555
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23556
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23557
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23558
 * Called inside tcp_rput when a message built using
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23559
 * tcp_ioctl_abort_build_msg is put into a queue.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23560
 * Note that when we get here there is no wildcard in acp any more.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23561
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23562
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23563
tcp_ioctl_abort_handler(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23564
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23565
	tcp_ioc_abort_conn_t *acp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23566
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23567
	acp = (tcp_ioc_abort_conn_t *)(mp->b_rptr + sizeof (uint32_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23568
	if (tcp->tcp_state <= acp->ac_end) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23569
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23570
		 * If we get here, we are already on the correct
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23571
		 * squeue. This ioctl follows the following path
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23572
		 * tcp_wput -> tcp_wput_ioctl -> tcp_ioctl_abort_conn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23573
		 * ->tcp_ioctl_abort->squeue_fill (if on a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23574
		 * different squeue)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23575
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23576
		int errcode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23577
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23578
		TCP_AC_GET_ERRCODE(tcp->tcp_state, errcode);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23579
		(void) tcp_clean_death(tcp, errcode, 26);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23580
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23581
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23582
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23583
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23584
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23585
 * Abort all matching connections on a hash chain.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23586
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23587
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23588
tcp_ioctl_abort_bucket(tcp_ioc_abort_conn_t *acp, int index, int *count,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23589
    boolean_t exact)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23590
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23591
	int nmatch, err = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23592
	tcp_t *tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23593
	MBLKP mp, last, listhead = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23594
	conn_t	*tconnp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23595
	connf_t	*connfp = &ipcl_conn_fanout[index];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23596
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23597
startover:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23598
	nmatch = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23599
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23600
	mutex_enter(&connfp->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23601
	for (tconnp = connfp->connf_head; tconnp != NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23602
	    tconnp = tconnp->conn_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23603
		tcp = tconnp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23604
		if (TCP_AC_MATCH(acp, tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23605
			CONN_INC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23606
			mp = tcp_ioctl_abort_build_msg(acp, tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23607
			if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23608
				err = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23609
				CONN_DEC_REF(tcp->tcp_connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23610
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23611
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23612
			mp->b_prev = (mblk_t *)tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23613
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23614
			if (listhead == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23615
				listhead = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23616
				last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23617
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23618
				last->b_next = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23619
				last = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23620
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23621
			nmatch++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23622
			if (exact)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23623
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23624
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23625
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23626
		/* Avoid holding lock for too long. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23627
		if (nmatch >= 500)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23628
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23629
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23630
	mutex_exit(&connfp->connf_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23631
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23632
	/* Pass mp into the correct tcp */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23633
	while ((mp = listhead) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23634
		listhead = listhead->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23635
		tcp = (tcp_t *)mp->b_prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23636
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23637
		squeue_fill(tcp->tcp_connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23638
		    tcp_input, tcp->tcp_connp, SQTAG_TCP_ABORT_BUCKET);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23639
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23641
	*count += nmatch;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23642
	if (nmatch >= 500 && err == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23643
		goto startover;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23644
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23645
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23646
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23647
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23648
 * Abort all connections that matches the attributes specified in acp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23649
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23650
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23651
tcp_ioctl_abort(tcp_ioc_abort_conn_t *acp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23652
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23653
	sa_family_t af;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23654
	uint32_t  ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23655
	uint16_t *pports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23656
	int err = 0, count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23657
	boolean_t exact = B_FALSE; /* set when there is no wildcard */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23658
	int index = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23659
	ushort_t logflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23660
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23661
	af = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23662
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23663
	if (af == AF_INET) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23664
		if (TCP_AC_V4REMOTE(acp) != INADDR_ANY &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23665
		    TCP_AC_V4LPORT(acp) != 0 && TCP_AC_V4RPORT(acp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23666
			pports = (uint16_t *)&ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23667
			pports[1] = TCP_AC_V4LPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23668
			pports[0] = TCP_AC_V4RPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23669
			exact = (TCP_AC_V4LOCAL(acp) != INADDR_ANY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23670
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23671
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23672
		if (!IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6REMOTE(acp)) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23673
		    TCP_AC_V6LPORT(acp) != 0 && TCP_AC_V6RPORT(acp) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23674
			pports = (uint16_t *)&ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23675
			pports[1] = TCP_AC_V6LPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23676
			pports[0] = TCP_AC_V6RPORT(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23677
			exact = !IN6_IS_ADDR_UNSPECIFIED(&TCP_AC_V6LOCAL(acp));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23678
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23679
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23681
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23682
	 * For cases where remote addr, local port, and remote port are non-
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23683
	 * wildcards, tcp_ioctl_abort_bucket will only be called once.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23684
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23685
	if (index != -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23686
		err = tcp_ioctl_abort_bucket(acp, index,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23687
			    &count, exact);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23688
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23689
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23690
		 * loop through all entries for wildcard case
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23691
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23692
		for (index = 0; index < ipcl_conn_fanout_size; index++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23693
			err = tcp_ioctl_abort_bucket(acp, index,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23694
			    &count, exact);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23695
			if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23696
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23697
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23698
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23699
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23700
	logflags = SL_TRACE | SL_NOTE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23701
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23702
	 * Don't print this message to the console if the operation was done
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23703
	 * to a non-global zone.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23704
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23705
	if (acp->ac_zoneid == GLOBAL_ZONEID || acp->ac_zoneid == ALL_ZONES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23706
		logflags |= SL_CONSOLE;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 23707
	(void) strlog(TCP_MOD_ID, 0, 1, logflags, "TCP_IOC_ABORT_CONN: "
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23708
	    "aborted %d connection%c\n", count, ((count > 1) ? 's' : ' '));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23709
	if (err == 0 && count == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23710
		err = ENOENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23711
	return (err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23712
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23714
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23715
 * Process the TCP_IOC_ABORT_CONN ioctl request.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23716
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23717
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23718
tcp_ioctl_abort_conn(queue_t *q, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23719
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23720
	int	err;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23721
	IOCP    iocp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23722
	MBLKP   mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23723
	sa_family_t laf, raf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23724
	tcp_ioc_abort_conn_t *acp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23725
	zone_t *zptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23726
	zoneid_t zoneid = Q_TO_CONN(q)->conn_zoneid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23727
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23728
	iocp = (IOCP)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23729
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23730
	if ((mp1 = mp->b_cont) == NULL ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23731
	    iocp->ioc_count != sizeof (tcp_ioc_abort_conn_t)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23732
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23733
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23734
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23735
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23736
	/* check permissions */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23737
	if (secpolicy_net_config(iocp->ioc_cr, B_FALSE) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23738
		err = EPERM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23739
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23740
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23741
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23742
	if (mp1->b_cont != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23743
		freemsg(mp1->b_cont);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23744
		mp1->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23745
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23746
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23747
	acp = (tcp_ioc_abort_conn_t *)mp1->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23748
	laf = acp->ac_local.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23749
	raf = acp->ac_remote.ss_family;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23750
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23751
	/* check that a zone with the supplied zoneid exists */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23752
	if (acp->ac_zoneid != GLOBAL_ZONEID && acp->ac_zoneid != ALL_ZONES) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23753
		zptr = zone_find_by_id(zoneid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23754
		if (zptr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23755
			zone_rele(zptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23756
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23757
			err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23758
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23759
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23760
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23761
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23762
	if (acp->ac_start < TCPS_SYN_SENT || acp->ac_end > TCPS_TIME_WAIT ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23763
	    acp->ac_start > acp->ac_end || laf != raf ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23764
	    (laf != AF_INET && laf != AF_INET6)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23765
		err = EINVAL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23766
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23767
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23768
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23769
	tcp_ioctl_abort_dump(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23770
	err = tcp_ioctl_abort(acp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23771
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23772
out:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23773
	if (mp1 != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23774
		freemsg(mp1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23775
		mp->b_cont = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23776
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23777
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23778
	if (err != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23779
		miocnak(q, mp, 0, err);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23780
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23781
		miocack(q, mp, 0, 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23782
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23783
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23784
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23785
 * tcp_time_wait_processing() handles processing of incoming packets when
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23786
 * the tcp is in the TIME_WAIT state.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23787
 * A TIME_WAIT tcp that has an associated open TCP stream is never put
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23788
 * on the time wait list.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23789
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23790
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23791
tcp_time_wait_processing(tcp_t *tcp, mblk_t *mp, uint32_t seg_seq,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23792
    uint32_t seg_ack, int seg_len, tcph_t *tcph)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23793
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23794
	int32_t		bytes_acked;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23795
	int32_t		gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23796
	int32_t		rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23797
	tcp_opt_t	tcpopt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23798
	uint_t		flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23799
	uint32_t	new_swnd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23800
	conn_t		*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23801
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23802
	BUMP_LOCAL(tcp->tcp_ibsegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23803
	TCP_RECORD_TRACE(tcp, mp, TCP_TRACE_RECV_PKT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23804
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23805
	flags = (unsigned int)tcph->th_flags[0] & 0xFF;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23806
	new_swnd = BE16_TO_U16(tcph->th_win) <<
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23807
	    ((tcph->th_flags[0] & TH_SYN) ? 0 : tcp->tcp_snd_ws);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23808
	if (tcp->tcp_snd_ts_ok) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23809
		if (!tcp_paws_check(tcp, tcph, &tcpopt)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23810
			tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23811
			    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23812
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23813
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23814
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23815
	gap = seg_seq - tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23816
	rgap = tcp->tcp_rwnd - (gap + seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23817
	if (gap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23818
		BUMP_MIB(&tcp_mib, tcpInDataDupSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23819
		UPDATE_MIB(&tcp_mib, tcpInDataDupBytes,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23820
		    (seg_len > -gap ? -gap : seg_len));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23821
		seg_len += gap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23822
		if (seg_len < 0 || (seg_len == 0 && !(flags & TH_FIN))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23823
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23824
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23825
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23826
			if ((flags & TH_FIN) && seg_len == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23827
				/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23828
				 * When TCP receives a duplicate FIN in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23829
				 * TIME_WAIT state, restart the 2 MSL timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23830
				 * See page 73 in RFC 793. Make sure this TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23831
				 * is already on the TIME_WAIT list. If not,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23832
				 * just restart the timer.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23833
				 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23834
				if (TCP_IS_DETACHED(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23835
					tcp_time_wait_remove(tcp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23836
					tcp_time_wait_append(tcp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23837
					TCP_DBGSTAT(tcp_rput_time_wait);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23838
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23839
					ASSERT(tcp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23840
					TCP_TIMER_RESTART(tcp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23841
					    tcp_time_wait_interval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23842
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23843
				tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23844
				    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23845
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23846
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23847
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23848
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23849
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23850
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23851
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23852
		/* Fix seg_seq, and chew the gap off the front. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23853
		seg_seq = tcp->tcp_rnxt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23854
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23855
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23856
	if ((flags & TH_SYN) && gap > 0 && rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23857
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23858
		 * Make sure that when we accept the connection, pick
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23859
		 * an ISS greater than (tcp_snxt + ISS_INCR/2) for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23860
		 * old connection.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23861
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23862
		 * The next ISS generated is equal to tcp_iss_incr_extra
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23863
		 * + ISS_INCR/2 + other components depending on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23864
		 * value of tcp_strong_iss.  We pre-calculate the new
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23865
		 * ISS here and compare with tcp_snxt to determine if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23866
		 * we need to make adjustment to tcp_iss_incr_extra.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23867
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23868
		 * The above calculation is ugly and is a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23869
		 * waste of CPU cycles...
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23870
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23871
		uint32_t new_iss = tcp_iss_incr_extra;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23872
		int32_t adj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23873
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23874
		switch (tcp_strong_iss) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23875
		case 2: {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23876
			/* Add time and MD5 components. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23877
			uint32_t answer[4];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23878
			struct {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23879
				uint32_t ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23880
				in6_addr_t src;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23881
				in6_addr_t dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23882
			} arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23883
			MD5_CTX context;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23884
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23885
			mutex_enter(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23886
			context = tcp_iss_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23887
			mutex_exit(&tcp_iss_key_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23888
			arg.ports = tcp->tcp_ports;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23889
			/* We use MAPPED addresses in tcp_iss_init */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23890
			arg.src = tcp->tcp_ip_src_v6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23891
			if (tcp->tcp_ipversion == IPV4_VERSION) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23892
				IN6_IPADDR_TO_V4MAPPED(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23893
					tcp->tcp_ipha->ipha_dst,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23894
					    &arg.dst);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23895
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23896
				arg.dst =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23897
				    tcp->tcp_ip6h->ip6_dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23898
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23899
			MD5Update(&context, (uchar_t *)&arg,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23900
			    sizeof (arg));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23901
			MD5Final((uchar_t *)answer, &context);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23902
			answer[0] ^= answer[1] ^ answer[2] ^ answer[3];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23903
			new_iss += (gethrtime() >> ISS_NSEC_SHT) + answer[0];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23904
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23905
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23906
		case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23907
			/* Add time component and min random (i.e. 1). */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23908
			new_iss += (gethrtime() >> ISS_NSEC_SHT) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23909
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23910
		default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23911
			/* Add only time component. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23912
			new_iss += (uint32_t)gethrestime_sec() * ISS_INCR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23913
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23914
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23915
		if ((adj = (int32_t)(tcp->tcp_snxt - new_iss)) > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23916
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23917
			 * New ISS not guaranteed to be ISS_INCR/2
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23918
			 * ahead of the current tcp_snxt, so add the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23919
			 * difference to tcp_iss_incr_extra.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23920
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23921
			tcp_iss_incr_extra += adj;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23922
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23923
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23924
		 * If tcp_clean_death() can not perform the task now,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23925
		 * drop the SYN packet and let the other side re-xmit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23926
		 * Otherwise pass the SYN packet back in, since the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23927
		 * old tcp state has been cleaned up or freed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23928
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23929
		if (tcp_clean_death(tcp, 0, 27) == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23930
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23931
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23932
		 * We will come back to tcp_rput_data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23933
		 * on the global queue. Packets destined
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23934
		 * for the global queue will be checked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23935
		 * with global policy. But the policy for
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23936
		 * this packet has already been checked as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23937
		 * this was destined for the detached
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23938
		 * connection. We need to bypass policy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23939
		 * check this time by attaching a dummy
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23940
		 * ipsec_in with ipsec_in_dont_check set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23941
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23942
		if ((connp = ipcl_classify(mp, tcp->tcp_connp->conn_zoneid)) !=
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23943
		    NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23944
			TCP_STAT(tcp_time_wait_syn_success);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23945
			tcp_reinput(connp, mp, tcp->tcp_connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23946
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23947
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23948
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23949
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23950
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23951
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23952
	 * rgap is the amount of stuff received out of window.  A negative
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23953
	 * value is the amount out of window.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23954
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23955
	if (rgap < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23956
		BUMP_MIB(&tcp_mib, tcpInDataPastWinSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23957
		UPDATE_MIB(&tcp_mib, tcpInDataPastWinBytes, -rgap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23958
		/* Fix seg_len and make sure there is something left. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23959
		seg_len += rgap;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23960
		if (seg_len <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23961
			if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23962
				goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23963
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23964
			flags |=  TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23965
			seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23966
			goto process_ack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23967
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23968
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23969
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23970
	 * Check whether we can update tcp_ts_recent.  This test is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23971
	 * NOT the one in RFC 1323 3.4.  It is from Braden, 1993, "TCP
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23972
	 * Extensions for High Performance: An Update", Internet Draft.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23973
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23974
	if (tcp->tcp_snd_ts_ok &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23975
	    TSTMP_GEQ(tcpopt.tcp_opt_ts_val, tcp->tcp_ts_recent) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23976
	    SEQ_LEQ(seg_seq, tcp->tcp_rack)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23977
		tcp->tcp_ts_recent = tcpopt.tcp_opt_ts_val;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23978
		tcp->tcp_last_rcv_lbolt = lbolt64;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23979
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23980
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23981
	if (seg_seq != tcp->tcp_rnxt && seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23982
		/* Always ack out of order packets */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23983
		flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23984
		seg_len = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23985
	} else if (seg_len > 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23986
		BUMP_MIB(&tcp_mib, tcpInClosed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23987
		BUMP_MIB(&tcp_mib, tcpInDataInorderSegs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23988
		UPDATE_MIB(&tcp_mib, tcpInDataInorderBytes, seg_len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23989
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23990
	if (flags & TH_RST) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23991
		(void) tcp_clean_death(tcp, 0, 28);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23992
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23993
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23994
	if (flags & TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23995
		tcp_xmit_ctl("TH_SYN", tcp, seg_ack, seg_seq + 1,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23996
		    TH_RST|TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23997
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23998
		 * Do not delete the TCP structure if it is in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 23999
		 * TIME_WAIT state.  Refer to RFC 1122, 4.2.2.13.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24000
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24001
		goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24002
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24003
process_ack:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24004
	if (flags & TH_ACK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24005
		bytes_acked = (int)(seg_ack - tcp->tcp_suna);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24006
		if (bytes_acked <= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24007
			if (bytes_acked == 0 && seg_len == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24008
			    new_swnd == tcp->tcp_swnd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24009
				BUMP_MIB(&tcp_mib, tcpInDupAck);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24010
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24011
			/* Acks something not sent */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24012
			flags |= TH_ACK_NEEDED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24013
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24014
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24015
	if (flags & TH_ACK_NEEDED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24016
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24017
		 * Time to send an ack for some reason.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24018
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24019
		tcp_xmit_ctl(NULL, tcp, tcp->tcp_snxt,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24020
		    tcp->tcp_rnxt, TH_ACK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24021
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24022
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24023
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24024
		DB_CKSUMSTART(mp) = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24025
		mp->b_datap->db_struioflag &= ~STRUIO_EAGER;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24026
		TCP_STAT(tcp_time_wait_syn_fail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24027
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24028
	freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24029
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24030
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24031
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24032
 * Return zero if the buffers are identical in length and content.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24033
 * This is used for comparing extension header buffers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24034
 * Note that an extension header would be declared different
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24035
 * even if all that changed was the next header value in that header i.e.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24036
 * what really changed is the next extension header.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24037
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24038
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24039
tcp_cmpbuf(void *a, uint_t alen, boolean_t b_valid, void *b, uint_t blen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24040
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24041
	if (!b_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24042
		blen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24043
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24044
	if (alen != blen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24045
		return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24046
	if (alen == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24047
		return (B_FALSE);	/* Both zero length */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24048
	return (bcmp(a, b, alen));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24049
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24050
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24051
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24052
 * Preallocate memory for tcp_savebuf(). Returns B_TRUE if ok.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24053
 * Return B_FALSE if memory allocation fails - don't change any state!
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24054
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24055
static boolean_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24056
tcp_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24057
    void *src, uint_t srclen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24058
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24059
	void *dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24061
	if (!src_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24062
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24063
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24064
	ASSERT(*dstlenp == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24065
	if (src != NULL && srclen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24066
		dst = mi_alloc(srclen, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24067
		if (dst == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24068
			return (B_FALSE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24069
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24070
		dst = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24071
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24072
	if (*dstp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24073
		mi_free(*dstp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24074
		*dstp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24075
		*dstlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24076
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24077
	*dstp = dst;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24078
	if (dst != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24079
		*dstlenp = srclen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24080
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24081
		*dstlenp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24082
	return (B_TRUE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24083
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24084
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24085
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24086
 * Replace what is in *dst, *dstlen with the source.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24087
 * Assumes tcp_allocbuf has already been called.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24088
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24089
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24090
tcp_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24091
    void *src, uint_t srclen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24092
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24093
	if (!src_valid)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24094
		srclen = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24095
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24096
	ASSERT(*dstlenp == srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24097
	if (src != NULL && srclen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24098
		bcopy(src, *dstp, srclen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24099
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24100
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24102
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24103
 * Allocate a T_SVR4_OPTMGMT_REQ.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24104
 * The caller needs to increment tcp_drop_opt_ack_cnt when sending these so
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24105
 * that tcp_rput_other can drop the acks.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24106
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24107
static mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24108
tcp_setsockopt_mp(int level, int cmd, char *opt, int optlen)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24109
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24110
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24111
	struct T_optmgmt_req *tor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24112
	struct opthdr *oh;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24113
	uint_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24114
	char *optptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24115
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24116
	size = sizeof (*tor) + sizeof (*oh) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24117
	mp = allocb(size, BPRI_MED);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24118
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24119
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24121
	mp->b_wptr += size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24122
	mp->b_datap->db_type = M_PROTO;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24123
	tor = (struct T_optmgmt_req *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24124
	tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24125
	tor->MGMT_flags = T_NEGOTIATE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24126
	tor->OPT_length = sizeof (*oh) + optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24127
	tor->OPT_offset = (t_scalar_t)sizeof (*tor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24129
	oh = (struct opthdr *)&tor[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24130
	oh->level = level;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24131
	oh->name = cmd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24132
	oh->len = optlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24133
	if (optlen != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24134
		optptr = (char *)&oh[1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24135
		bcopy(opt, optptr, optlen);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24136
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24137
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24138
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24139
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24140
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24141
 * TCP Timers Implementation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24142
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24143
timeout_id_t
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24144
tcp_timeout(conn_t *connp, void (*f)(void *), clock_t tim)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24145
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24146
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24147
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24148
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24149
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24150
	ASSERT(connp->conn_sqp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24152
	TCP_DBGSTAT(tcp_timeout_calls);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24154
	if (tcp->tcp_timercache == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24155
		mp = tcp_timermp_alloc(KM_NOSLEEP | KM_PANIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24156
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24157
		TCP_DBGSTAT(tcp_timeout_cached_alloc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24158
		mp = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24159
		tcp->tcp_timercache = mp->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24160
		mp->b_next = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24161
		ASSERT(mp->b_wptr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24162
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24164
	CONN_INC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24165
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24166
	tcpt->connp = connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24167
	tcpt->tcpt_proc = f;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24168
	tcpt->tcpt_tid = timeout(tcp_timer_callback, mp, tim);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24169
	return ((timeout_id_t)mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24170
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24172
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24173
tcp_timer_callback(void *arg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24174
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24175
	mblk_t *mp = (mblk_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24176
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24177
	conn_t	*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24179
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24180
	connp = tcpt->connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24181
	squeue_fill(connp->conn_sqp, mp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24182
	    tcp_timer_handler, connp, SQTAG_TCP_TIMER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24183
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24184
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24185
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24186
tcp_timer_handler(void *arg, mblk_t *mp, void *arg2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24187
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24188
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24189
	conn_t *connp = (conn_t *)arg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24190
	tcp_t *tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24191
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24192
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24193
	ASSERT(connp == tcpt->connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24194
	ASSERT((squeue_t *)arg2 == connp->conn_sqp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24196
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24197
	 * If the TCP has reached the closed state, don't proceed any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24198
	 * further. This TCP logically does not exist on the system.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24199
	 * tcpt_proc could for example access queues, that have already
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24200
	 * been qprocoff'ed off. Also see comments at the start of tcp_input
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24201
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24202
	if (tcp->tcp_state != TCPS_CLOSED) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24203
		(*tcpt->tcpt_proc)(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24204
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24205
		tcp->tcp_timer_tid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24206
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24207
	tcp_timer_free(connp->conn_tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24208
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24210
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24211
 * There is potential race with untimeout and the handler firing at the same
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24212
 * time. The mblock may be freed by the handler while we are trying to use
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24213
 * it. But since both should execute on the same squeue, this race should not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24214
 * occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24215
 */
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24216
clock_t
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24217
tcp_timeout_cancel(conn_t *connp, timeout_id_t id)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24218
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24219
	mblk_t	*mp = (mblk_t *)id;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24220
	tcp_timer_t *tcpt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24221
	clock_t delta;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24222
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24223
	TCP_DBGSTAT(tcp_timeout_cancel_reqs);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24224
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24225
	if (mp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24226
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24227
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24228
	tcpt = (tcp_timer_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24229
	ASSERT(tcpt->connp == connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24230
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24231
	delta = untimeout(tcpt->tcpt_tid);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24233
	if (delta >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24234
		TCP_DBGSTAT(tcp_timeout_canceled);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24235
		tcp_timer_free(connp->conn_tcp, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24236
		CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24237
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24238
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24239
	return (delta);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24240
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24241
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24242
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24243
 * Allocate space for the timer event. The allocation looks like mblk, but it is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24244
 * not a proper mblk. To avoid confusion we set b_wptr to NULL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24245
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24246
 * Dealing with failures: If we can't allocate from the timer cache we try
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24247
 * allocating from dblock caches using allocb_tryhard(). In this case b_wptr
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24248
 * points to b_rptr.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24249
 * If we can't allocate anything using allocb_tryhard(), we perform a last
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24250
 * attempt and use kmem_alloc_tryhard(). In this case we set b_wptr to -1 and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24251
 * save the actual allocation size in b_datap.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24252
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24253
mblk_t *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24254
tcp_timermp_alloc(int kmflags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24255
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24256
	mblk_t *mp = (mblk_t *)kmem_cache_alloc(tcp_timercache,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24257
	    kmflags & ~KM_PANIC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24259
	if (mp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24260
		mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24261
		mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24262
		mp->b_wptr = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24263
		mp->b_datap = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24264
		mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24265
	} else if (kmflags & KM_PANIC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24266
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24267
		 * Failed to allocate memory for the timer. Try allocating from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24268
		 * dblock caches.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24269
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24270
		TCP_STAT(tcp_timermp_allocfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24271
		mp = allocb_tryhard(sizeof (tcp_timer_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24272
		if (mp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24273
			size_t size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24274
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24275
			 * Memory is really low. Try tryhard allocation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24276
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24277
			TCP_STAT(tcp_timermp_allocdblfail);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24278
			mp = kmem_alloc_tryhard(sizeof (mblk_t) +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24279
			    sizeof (tcp_timer_t), &size, kmflags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24280
			mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24281
			mp->b_next = mp->b_prev = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24282
			mp->b_wptr = (uchar_t *)-1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24283
			mp->b_datap = (dblk_t *)size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24284
			mp->b_queue = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24285
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24286
		ASSERT(mp->b_wptr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24287
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24288
	TCP_DBGSTAT(tcp_timermp_alloced);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24290
	return (mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24291
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24292
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24293
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24294
 * Free per-tcp timer cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24295
 * It can only contain entries from tcp_timercache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24296
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24297
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24298
tcp_timermp_free(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24299
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24300
	mblk_t *mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24302
	while ((mp = tcp->tcp_timercache) != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24303
		ASSERT(mp->b_wptr == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24304
		tcp->tcp_timercache = tcp->tcp_timercache->b_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24305
		kmem_cache_free(tcp_timercache, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24306
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24307
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24308
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24309
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24310
 * Free timer event. Put it on the per-tcp timer cache if there is not too many
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24311
 * events there already (currently at most two events are cached).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24312
 * If the event is not allocated from the timer cache, free it right away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24313
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24314
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24315
tcp_timer_free(tcp_t *tcp, mblk_t *mp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24316
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24317
	mblk_t *mp1 = tcp->tcp_timercache;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24318
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24319
	if (mp->b_wptr != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24320
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24321
		 * This allocation is not from a timer cache, free it right
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24322
		 * away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24323
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24324
		if (mp->b_wptr != (uchar_t *)-1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24325
			freeb(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24326
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24327
			kmem_free(mp, (size_t)mp->b_datap);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24328
	} else if (mp1 == NULL || mp1->b_next == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24329
		/* Cache this timer block for future allocations */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24330
		mp->b_rptr = (uchar_t *)(&mp[1]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24331
		mp->b_next = mp1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24332
		tcp->tcp_timercache = mp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24333
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24334
		kmem_cache_free(tcp_timercache, mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24335
		TCP_DBGSTAT(tcp_timermp_freed);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24336
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24337
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24339
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24340
 * End of TCP Timers implementation.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24341
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24342
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24343
/*
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24344
 * tcp_{set,clr}qfull() functions are used to either set or clear QFULL
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24345
 * on the specified backing STREAMS q. Note, the caller may make the
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24346
 * decision to call based on the tcp_t.tcp_flow_stopped value which
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24347
 * when check outside the q's lock is only an advisory check ...
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24348
 */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24349
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24350
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24351
tcp_setqfull(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24352
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24353
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24354
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24355
	if (!(q->q_flag & QFULL)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24356
		mutex_enter(QLOCK(q));
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24357
		if (!(q->q_flag & QFULL)) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24358
			/* still need to set QFULL */
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24359
			q->q_flag |= QFULL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24360
			tcp->tcp_flow_stopped = B_TRUE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24361
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24362
			TCP_STAT(tcp_flwctl_on);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24363
		} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24364
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24365
		}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24366
	}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24367
}
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24368
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24369
void
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24370
tcp_clrqfull(tcp_t *tcp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24371
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24372
	queue_t *q = tcp->tcp_wq;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24374
	if (q->q_flag & QFULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24375
		mutex_enter(QLOCK(q));
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24376
		if (q->q_flag & QFULL) {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24377
			q->q_flag &= ~QFULL;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24378
			tcp->tcp_flow_stopped = B_FALSE;
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24379
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24380
			if (q->q_flag & QWANTW)
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24381
				qbackenable(q, 0);
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24382
		} else {
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24383
			mutex_exit(QLOCK(q));
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24384
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24385
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24386
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24387
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24388
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24389
 * TCP Kstats implementation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24390
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24391
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24392
tcp_kstat_init(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24393
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24394
	tcp_named_kstat_t template = {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24395
		{ "rtoAlgorithm",	KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24396
		{ "rtoMin",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24397
		{ "rtoMax",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24398
		{ "maxConn",		KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24399
		{ "activeOpens",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24400
		{ "passiveOpens",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24401
		{ "attemptFails",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24402
		{ "estabResets",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24403
		{ "currEstab",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24404
		{ "inSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24405
		{ "outSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24406
		{ "retransSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24407
		{ "connTableSize",	KSTAT_DATA_INT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24408
		{ "outRsts",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24409
		{ "outDataSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24410
		{ "outDataBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24411
		{ "retransBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24412
		{ "outAck",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24413
		{ "outAckDelayed",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24414
		{ "outUrg",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24415
		{ "outWinUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24416
		{ "outWinProbe",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24417
		{ "outControl",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24418
		{ "outFastRetrans",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24419
		{ "inAckSegs",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24420
		{ "inAckBytes",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24421
		{ "inDupAck",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24422
		{ "inAckUnsent",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24423
		{ "inDataInorderSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24424
		{ "inDataInorderBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24425
		{ "inDataUnorderSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24426
		{ "inDataUnorderBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24427
		{ "inDataDupSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24428
		{ "inDataDupBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24429
		{ "inDataPartDupSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24430
		{ "inDataPartDupBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24431
		{ "inDataPastWinSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24432
		{ "inDataPastWinBytes",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24433
		{ "inWinProbe",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24434
		{ "inWinUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24435
		{ "inClosed",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24436
		{ "rttUpdate",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24437
		{ "rttNoUpdate",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24438
		{ "timRetrans",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24439
		{ "timRetransDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24440
		{ "timKeepalive",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24441
		{ "timKeepaliveProbe",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24442
		{ "timKeepaliveDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24443
		{ "listenDrop",		KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24444
		{ "listenDropQ0",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24445
		{ "halfOpenDrop",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24446
		{ "outSackRetransSegs",	KSTAT_DATA_UINT32, 0 },
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24447
		{ "connTableSize6",	KSTAT_DATA_INT32, 0 }
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24448
	};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24449
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24450
	tcp_mibkp = kstat_create(TCP_MOD_NAME, 0, TCP_MOD_NAME,
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24451
	    "mib2", KSTAT_TYPE_NAMED, NUM_OF_FIELDS(tcp_named_kstat_t), 0);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24452
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24453
	if (tcp_mibkp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24454
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24455
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24456
	template.rtoAlgorithm.value.ui32 = 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24457
	template.rtoMin.value.ui32 = tcp_rexmit_interval_min;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24458
	template.rtoMax.value.ui32 = tcp_rexmit_interval_max;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24459
	template.maxConn.value.i32 = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24460
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24461
	bcopy(&template, tcp_mibkp->ks_data, sizeof (template));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24462
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24463
	tcp_mibkp->ks_update = tcp_kstat_update;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24464
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24465
	kstat_install(tcp_mibkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24466
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24467
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24468
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24469
tcp_kstat_fini(void)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24470
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24471
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24472
	if (tcp_mibkp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24473
		kstat_delete(tcp_mibkp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24474
		tcp_mibkp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24475
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24476
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24477
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24478
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24479
tcp_kstat_update(kstat_t *kp, int rw)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24480
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24481
	tcp_named_kstat_t	*tcpkp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24482
	tcp_t			*tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24483
	connf_t			*connfp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24484
	conn_t			*connp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24485
	int 			i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24486
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24487
	if (!kp || !kp->ks_data)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24488
		return (EIO);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24489
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24490
	if (rw == KSTAT_WRITE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24491
		return (EACCES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24492
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24493
	tcpkp = (tcp_named_kstat_t *)kp->ks_data;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24494
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24495
	tcpkp->currEstab.value.ui32 = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24496
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24497
	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24498
		connfp = &ipcl_globalhash_fanout[i];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24499
		connp = NULL;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24500
		while ((connp =
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24501
		    ipcl_get_next_conn(connfp, connp, IPCL_TCP)) != NULL) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24502
			tcp = connp->conn_tcp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24503
			switch (tcp_snmp_state(tcp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24504
			case MIB2_TCP_established:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24505
			case MIB2_TCP_closeWait:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24506
				tcpkp->currEstab.value.ui32++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24507
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24508
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24509
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24510
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24511
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24512
	tcpkp->activeOpens.value.ui32 = tcp_mib.tcpActiveOpens;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24513
	tcpkp->passiveOpens.value.ui32 = tcp_mib.tcpPassiveOpens;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24514
	tcpkp->attemptFails.value.ui32 = tcp_mib.tcpAttemptFails;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24515
	tcpkp->estabResets.value.ui32 = tcp_mib.tcpEstabResets;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24516
	tcpkp->inSegs.value.ui32 = tcp_mib.tcpInSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24517
	tcpkp->outSegs.value.ui32 = tcp_mib.tcpOutSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24518
	tcpkp->retransSegs.value.ui32 =	tcp_mib.tcpRetransSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24519
	tcpkp->connTableSize.value.i32 = tcp_mib.tcpConnTableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24520
	tcpkp->outRsts.value.ui32 = tcp_mib.tcpOutRsts;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24521
	tcpkp->outDataSegs.value.ui32 = tcp_mib.tcpOutDataSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24522
	tcpkp->outDataBytes.value.ui32 = tcp_mib.tcpOutDataBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24523
	tcpkp->retransBytes.value.ui32 = tcp_mib.tcpRetransBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24524
	tcpkp->outAck.value.ui32 = tcp_mib.tcpOutAck;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24525
	tcpkp->outAckDelayed.value.ui32 = tcp_mib.tcpOutAckDelayed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24526
	tcpkp->outUrg.value.ui32 = tcp_mib.tcpOutUrg;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24527
	tcpkp->outWinUpdate.value.ui32 = tcp_mib.tcpOutWinUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24528
	tcpkp->outWinProbe.value.ui32 = tcp_mib.tcpOutWinProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24529
	tcpkp->outControl.value.ui32 = tcp_mib.tcpOutControl;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24530
	tcpkp->outFastRetrans.value.ui32 = tcp_mib.tcpOutFastRetrans;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24531
	tcpkp->inAckSegs.value.ui32 = tcp_mib.tcpInAckSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24532
	tcpkp->inAckBytes.value.ui32 = tcp_mib.tcpInAckBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24533
	tcpkp->inDupAck.value.ui32 = tcp_mib.tcpInDupAck;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24534
	tcpkp->inAckUnsent.value.ui32 = tcp_mib.tcpInAckUnsent;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24535
	tcpkp->inDataInorderSegs.value.ui32 = tcp_mib.tcpInDataInorderSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24536
	tcpkp->inDataInorderBytes.value.ui32 = tcp_mib.tcpInDataInorderBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24537
	tcpkp->inDataUnorderSegs.value.ui32 = tcp_mib.tcpInDataUnorderSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24538
	tcpkp->inDataUnorderBytes.value.ui32 = tcp_mib.tcpInDataUnorderBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24539
	tcpkp->inDataDupSegs.value.ui32 = tcp_mib.tcpInDataDupSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24540
	tcpkp->inDataDupBytes.value.ui32 = tcp_mib.tcpInDataDupBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24541
	tcpkp->inDataPartDupSegs.value.ui32 = tcp_mib.tcpInDataPartDupSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24542
	tcpkp->inDataPartDupBytes.value.ui32 = tcp_mib.tcpInDataPartDupBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24543
	tcpkp->inDataPastWinSegs.value.ui32 = tcp_mib.tcpInDataPastWinSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24544
	tcpkp->inDataPastWinBytes.value.ui32 = tcp_mib.tcpInDataPastWinBytes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24545
	tcpkp->inWinProbe.value.ui32 = tcp_mib.tcpInWinProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24546
	tcpkp->inWinUpdate.value.ui32 = tcp_mib.tcpInWinUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24547
	tcpkp->inClosed.value.ui32 = tcp_mib.tcpInClosed;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24548
	tcpkp->rttNoUpdate.value.ui32 = tcp_mib.tcpRttNoUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24549
	tcpkp->rttUpdate.value.ui32 = tcp_mib.tcpRttUpdate;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24550
	tcpkp->timRetrans.value.ui32 = tcp_mib.tcpTimRetrans;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24551
	tcpkp->timRetransDrop.value.ui32 = tcp_mib.tcpTimRetransDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24552
	tcpkp->timKeepalive.value.ui32 = tcp_mib.tcpTimKeepalive;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24553
	tcpkp->timKeepaliveProbe.value.ui32 = tcp_mib.tcpTimKeepaliveProbe;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24554
	tcpkp->timKeepaliveDrop.value.ui32 = tcp_mib.tcpTimKeepaliveDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24555
	tcpkp->listenDrop.value.ui32 = tcp_mib.tcpListenDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24556
	tcpkp->listenDropQ0.value.ui32 = tcp_mib.tcpListenDropQ0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24557
	tcpkp->halfOpenDrop.value.ui32 = tcp_mib.tcpHalfOpenDrop;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24558
	tcpkp->outSackRetransSegs.value.ui32 = tcp_mib.tcpOutSackRetransSegs;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24559
	tcpkp->connTableSize6.value.i32 = tcp_mib.tcp6ConnTableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24560
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24561
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24562
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24564
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24565
tcp_reinput(conn_t *connp, mblk_t *mp, squeue_t *sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24566
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24567
	uint16_t	hdr_len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24568
	ipha_t		*ipha;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24569
	uint8_t		*nexthdrp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24570
	tcph_t		*tcph;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24572
	/* Already has an eager */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24573
	if ((mp->b_datap->db_struioflag & STRUIO_EAGER) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24574
		TCP_STAT(tcp_reinput_syn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24575
		squeue_enter(connp->conn_sqp, mp, connp->conn_recv,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24576
		    connp, SQTAG_TCP_REINPUT_EAGER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24577
		return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24578
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24579
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24580
	switch (IPH_HDR_VERSION(mp->b_rptr)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24581
	case IPV4_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24582
		ipha = (ipha_t *)mp->b_rptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24583
		hdr_len = IPH_HDR_LENGTH(ipha);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24584
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24585
	case IPV6_VERSION:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24586
		if (!ip_hdr_length_nexthdr_v6(mp, (ip6_t *)mp->b_rptr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24587
		    &hdr_len, &nexthdrp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24588
			CONN_DEC_REF(connp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24589
			freemsg(mp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24590
			return;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24591
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24592
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24593
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24594
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24595
	tcph = (tcph_t *)&mp->b_rptr[hdr_len];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24596
	if ((tcph->th_flags[0] & (TH_SYN|TH_ACK|TH_RST|TH_URG)) == TH_SYN) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24597
		mp->b_datap->db_struioflag |= STRUIO_EAGER;
741
40027a3621ac PSARC 2005/082 Yosemite: UDP Performance Enhancement
masputra
parents: 740
diff changeset
 24598
		DB_CKSUMSTART(mp) = (intptr_t)sqp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24599
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24600
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24601
	squeue_fill(connp->conn_sqp, mp, connp->conn_recv, connp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24602
	    SQTAG_TCP_REINPUT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24603
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24604
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24605
static squeue_func_t
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24606
tcp_squeue_switch(int val)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24607
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24608
	squeue_func_t rval = squeue_fill;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24609
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24610
	switch (val) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24611
	case 1:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24612
		rval = squeue_enter_nodrain;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24613
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24614
	case 2:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24615
		rval = squeue_enter;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24616
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24617
	default:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24618
		break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24619
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24620
	return (rval);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24621
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24622
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24623
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24624
tcp_squeue_add(squeue_t *sqp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24625
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24626
	tcp_squeue_priv_t *tcp_time_wait = kmem_zalloc(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24627
		sizeof (tcp_squeue_priv_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24629
	*squeue_getprivate(sqp, SQPRIVATE_TCP) = (intptr_t)tcp_time_wait;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24630
	tcp_time_wait->tcp_time_wait_tid = timeout(tcp_time_wait_collector,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24631
	    sqp, TCP_TIME_WAIT_DELAY);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
 24632
}